My user entity:
public class User : IdentityUser<long>
{
public Office Office { get; set; } // not nullable
// ...other custom properties
}
Suppose I want to create a new user:
var user = new User {
UserName = "foo",
Email = "foo@example.com",
EmailConfirmed = true,
Office = await context.Offices.SingleAsync(x => x.Name == "Head Office"),
};
await _userManager.CreateAsync(user, "password");
That throws:
duplicate key value violates unique constraint "PK_Office"
The reason is that Office
was loaded in one context and used in the one encapsulated by UserManager
(which tries to create a new one with the same PK).
The underlying context is not exposed, so one can't do userManager.Context.Attach(office)
or similar.
I can see two workarounds:
User.Office
as nullable, then:
var user = ...
await _userManager.CreateAsync(user, "password");
user.Office = ...
_context.Attach(user);
await _context.SaveChangesAsync();
But I do not want to do that: I don't want to break my domain model (a user cannot exist without an office) because of a technical limitation in UserManager
DbContext
instead of UserManager
. But I do not want to do that either, because it handles all the auth-related stuff for me, and I don't want to take responsibility for any of that.What other options exist?
(In case it is relevant: this is not in the context of a web request, but actually in a console app.)
After much investigating here's what I found: if DbContext
and UserManager
are resolved from the same container, then the latter's underlying context will be the same instance as the former. (It is unfortunate though that it doesn't expose the context, so it can be used via Attach
).
It didn't work that way for me because in my console app, the two things were resolved from two containers.
The best option is to ensure they are resolved from the same container (i.e. ServiceProvider
).
If that's not possible then there are alternatives:
Office
entity, and then user.OfficeId = officeId
.