Concurrency Failure while updateng user

DiamondKesha 51 Reputation points
2024-10-23T14:59:32.0066667+00:00

Hi. After adding new item in List<RefreshToken> in user entity and update it in UserManager.UpdateAsync() me getting error "Optimistic concurrency failure, object has been modified". How i can fix it?

public class User : IdentityUser
{
    private readonly List<RefreshToken> _refreshTokens = [];

    public string Nickname { get; set; } = string.Empty;

    public IReadOnlyList<RefreshToken> RefreshTokens => _refreshTokens.AsReadOnly();

    public void AddRefreshToken(string refreshToken, DateTime expiryTime, string fingerprint, string ip)
    {
        _refreshTokens.Add(RefreshToken.Create(refreshToken, expiryTime, fingerprint, ip));
    }

    public void RemoveRefreshToken(string refreshToken)
    {
        var token = _refreshTokens.FirstOrDefault(x => x.Token == refreshToken);

        if (token is null) return;

        _refreshTokens.Remove(token);
    }
}

public class UserConfiguration : IEntityTypeConfiguration<User>
{
    public void Configure(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("Users");
        builder.HasKey(k => k.Id);

        builder.Property(p => p.Id)
            .ValueGeneratedOnAdd();

        builder.OwnsMany(o => o.RefreshTokens, n =>
        {
            n.ToTable("UserRefreshTokens");
            n.HasKey(k => k.Id);

            n.WithOwner().HasForeignKey("UserId");

            n.Property(p => p.CreatedTime);
            n.Property(p => p.ExpiryTime);
            n.Property(p => p.Fingerprint);
            n.Property(p => p.Ip);
        });
    }
}

        var user = await _userManager.FindByEmailAsync(request.Email);
        if (user is null)
        {
            errors.Add(Error.Validation("Wrong email or password"));
            return errors;
        }

        var result = await _signInManager.CheckPasswordSignInAsync(user, request.Password, false);
        if (!result.Succeeded)
        {
            errors.Add(Error.Validation("Wrong email or password"));
            return errors;
        }

        string accessToken = _tokenService.GenerateJwtToken(user);
        string refreshToken = _tokenService.GenerateRefreshToken();
        DateTime refreshTokenExpiryTime = DateTime.UtcNow.AddDays(Constants.IDENTITY_REFRESHTOKEN_EXPIRYDAYS);
        
        user.AddRefreshToken(refreshToken, refreshTokenExpiryTime, "Empty", "127.0.0.1");
        
        var resultUpdate = await _userManager.UpdateAsync(user);

.NET
.NET
Microsoft Technologies based on the .NET software framework.
3,907 questions
Blazor
Blazor
A free and open-source web framework that enables developers to create web apps using C# and HTML being developed by Microsoft.
1,595 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
11,001 questions
0 comments No comments
{count} votes

Accepted answer
  1. Hongrui Yu-MSFT 2,465 Reputation points Microsoft Vendor
    2024-10-24T08:20:50.7466667+00:00

    Hi,@DiamondKesha. Welcome to Microsoft Q&A. 

    You could try the following:

    Method 1:

    Catch and handle concurrency exceptions: When using UserManager for update operations, you could catch the DbUpdateConcurrencyException exception, and after catching the exception, reload the entity and try to save the changes again.

    Related Documents:  https://learn.microsoft.com/en-us/ef/core/saving/concurrency?tabs=data-annotations#resolving-concurrency-conflicts

    Method 2:

    Reference Documentation : c# - UserManager not updating User after changes to a property .net7 - Stack Overflow.

    a. Use DbContext Factory and Unit of Work context to solve this problem.

    b.Perform all operations synchronously.

    c.Override the ComponentBase UI handler HandleEventAsync with a version that does not call StateHasChanged.

    
    async Task IHandleEvent.HandleEventAsync(EventCallbackWorkItem callback, object? arg) => await callback.InvokeAsync(arg); 
    
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.