Search code examples
c#asp.net-coreentity-framework-coreuser-roles

c# - Adding a role to idenitity user on signup fails with foreign key constraint


I don't know if this is a duplicate, but I couldn't find any similar problems with solutions that helped in my case.

So I have an identity user that I want to add a role to based on which dropdown value the user chooses on signup page. I tested this part and it goes through just fine. But adding a role doesn't seem to work no matter what I try.

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
{
        returnUrl = returnUrl ?? Url.Content("~/");
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
        bool ownerRoleExists = await _roleManager.RoleExistsAsync("Owner");

        if (!ownerRoleExists)
        {
            var roleResult = await _roleManager.CreateAsync(new IdentityRole("Owner"));
        }

        bool patientRoleExists = await _roleManager.RoleExistsAsync("Patient");

        if (!patientRoleExists)
        {
            var roleResult = await _roleManager.CreateAsync(new IdentityRole("Patient"));
        }

        bool workerRoleExists = await _roleManager.RoleExistsAsync("Worker");

        if (!workerRoleExists)
        {
            var roleResult = await _roleManager.CreateAsync(new IdentityRole("Worker"));
        }

        if (ModelState.IsValid)
        {
            var user = new Person { UserName = Input.Email, Email = Input.Email, Name = Input.Name, LastName = Input.LastName, Address = Input.Address };
            var result = await _userManager.CreateAsync(user, Input.Password);

            if (result.Succeeded)
            {
                if (Input.PersonType.Equals("patient"))
                {
                    var patient = new Patient { PersonId = user.PersonId, VisitCount = 0, Number = Input.Number };
                    _context.Add(patient);
                    var patient_result = await _context.SaveChangesAsync();

                    if(patient_result > 0)
                    {
                        var result_role = await _userManager.AddToRoleAsync(user, "Patient");
                    }
                }
                else if(Input.PersonType.Equals("worker"))
                {
                    var worker = new Worker { PersonId = user.PersonId, WorkCode = Input.WorkCode };
                    _context.Add(worker);
                    var worker_result = await _context.SaveChangesAsync();

                    if(worker_result > 0)
                    {
                        var result_role = await _userManager.AddToRoleAsync(user, "Worker");
                    }
                }
                
                _logger.LogInformation("User created a new account with password.");
            }
        }
}

The error I get is:

SqlException: The INSERT statement conflicted with the FOREIGN KEY constraint "FK_AspNetUserRoles_person_UserId". The conflict occurred in database "hospital-prod", table "dbo.person", column 'person_id'.
The statement has been terminated.

The values I get from user are correct, when I checked in the debug right before role is added so variable user should be correct.

Also user and patient/worker are added to the database successfully, so only the role is a problem.


Solution

  • Okay, so I figured out what the real problem was; and I'm going to briefly explain it, if someone else is in the same situation at some point.

    The problem with adding a role in my case was that method AddToRoleAsync(User user, String role) accepts a User type variable not an ID, so it selects the ID by itself.

    Well, I have a custom database where i already have a person_id column and the rules of IdentityUser don't allow you to remove any of the default columns and that includes the Id. So the problem was that that method automaticay selected a wrong id and I had to change the behaviour of ids' to get it to work/select the right one.