-
Notifications
You must be signed in to change notification settings - Fork 151
Description
Description
I'd like to disable AutoSaveChanges (I also changed key type to int), then create user, add it to role and save it to database. CreateAsync is succcessful. However when I try to add user to role I'm getting following error:
{
"error": "The property 'User.Id' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property."
}
Steps to Reproduce
- Change key type to int
- Create CustomUserStore which inherits from UserStore
- Disable
AutoSaveChanges
- Run
UserManager::CreateAsync
- Run
UserManager::AddToRoleAsync
Actual result:
Error occurs:
{
"error": "The property 'User.Id' has a temporary value while attempting to change the entity's state to 'Unchanged'. Either set a permanent value explicitly, or ensure that the database is configured to generate values for this property."
}
Expected result:
User added to role
Did you find any workaround?
Yes. Looking at the identity code I noticed that internally UpdateAsync
is called after AddToRoleAsync
. UpdateAsync
calls Context.Attach
on the user object. However user object is already tracked and modified so that the exception is thrown. I changed UpdateAsync
in my custom user store to:
public override async Task<IdentityResult> UpdateAsync(User user, CancellationToken cancellationToken = default)
{
if (AutoSaveChanges)
{
return await base.UpdateAsync(user, cancellationToken);
}
return IdentityResult.Success;
}
but then different error occurred:
{
"error": "The value of 'UserRole.UserId' is unknown when attempting to save changes. This is because the property is also part of a foreign key for which the principal entity in the relationship is not known."
}
Looking at DebugView.LongView
I noticed that UserId
in UserRole
is different than Id
in User
so that relationship is wrong:
User {Id: -2147482647} Added
Id: -2147482647 PK Temporary
AccessFailedCount: 0
...
UserRole {UserId: -2147482646, RoleId: 1} Added
UserId: -2147482646 PK FK Temporary Unknown
RoleId: 1 PK FK
...
Id
which is set on User
entity is 0 but Id
tracked by EF is -2147482647. It seems that store does not recognize that Id
has temporary value and treats it as new one. To "fix" relationship I assigned UserId
in custom store:
protected override UserRole CreateUserRole(User user, Role role)
{
var currentValueId = Context.Entry(user).Property(e => e.Id).CurrentValue;
user.Id = currentValueId;
return base.CreateUserRole(user, role);
}
Now it's working without exceptions. However it seems that it should be handled correctly by Identity. It seems that UpdateAsync
is not needed to be called if AutoSaveChanges
is false as the caller already decided to do it by himself. Entity should be also recognized as temporary.