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.
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:
Steps to Reproduce
AutoSaveChangesUserManager::CreateAsyncUserManager::AddToRoleAsyncActual result:
Error occurs:
Expected result:
User added to role
Did you find any workaround?
Yes. Looking at the identity code I noticed that internally
UpdateAsyncis called afterAddToRoleAsync.UpdateAsynccallsContext.Attachon the user object. However user object is already tracked and modified so that the exception is thrown. I changedUpdateAsyncin my custom user store to:but then different error occurred:
Looking at
DebugView.LongViewI noticed thatUserIdinUserRoleis different thanIdinUserso that relationship is wrong:Idwhich is set onUserentity is 0 butIdtracked by EF is -2147482647. It seems that store does not recognize thatIdhas temporary value and treats it as new one. To "fix" relationship I assignedUserIdin custom store:Now it's working without exceptions. However it seems that it should be handled correctly by Identity. It seems that
UpdateAsyncis not needed to be called ifAutoSaveChangesis false as the caller already decided to do it by himself. Entity should be also recognized as temporary.