如何处理 IdentityUser 更新并发失败?

nic*_*tto 5 claims-based-identity claims asp.net-identity asp.net-core asp.net-core-1.0

我有一种方法可以在我们的应用程序中更新用户声明。

我以管理员用户身份登录,可以编辑其他用户。

我正在尝试删除一位用户的现有声明并分配新的声明。

结果UserManger是使用I删除声明时ConcurrencyFailure。(有时它可以工作,但大多数时候它会返回失败错误。)

代码:“并发失败”

描述:“乐观并发失败,对象已被修改。”

方法:

    public async Task<bool> AssignClaimsToUser(string id, List<string> newClaims)
    {
        bool success = false;

        ApplicationUser user = await _userManager.FindByIdAsync(id);
        List<Claim> userClaims = new List<Claim>();

        // Remove existing claims
        IList<Claim> existingClaims = await _userManager.GetClaimsAsync(user);
        var removal = await _userManager.RemoveClaimsAsync(user, existingClaims); // This fail

        if (removal.Succeeded)
        {
            success = true;

            // Add new claims
            foreach (string policy in newClaims)
            {
                userClaims.Add(new Claim(policy, string.Empty, ClaimValueTypes.String));
            }
            await _userManager.AddClaimsAsync(user, userClaims);
        }

        return success;
    }
Run Code Online (Sandbox Code Playgroud)

为什么会发生这种情况以及如何解决此问题?

我只有在删除声明时才会遇到这个问题。在 上调用其他方法时我没有它IdentityUser

编辑

调试输出:

在此处输入图片说明

Microsoft.AspNetCore.Hosting.Internal.WebHost:信息:请求开始 HTTP/1.1 POST http://localhost:47691/Users/ManageUsers_Update 应用程序/x-www-form-urlencoded; charset=UTF-8 246 Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: HttpContext.User 通过来自 authenticationScheme: Identity.Application 的 AutomaticAuthentication 合并。Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:用户授权成功:user@mydomain.com。Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:信息:用户授权成功:user@mydomain.com。Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: 使用参数 (Kendo.Mvc.UI.DataSourceRequest, MyProject.Views.ViewModels.ManageUsersViewModel) 执行操作方法 MyProject.Controllers.UsersController.ManageUsers_Update (MyProject) - ModelState 是有效的 Microsoft。 EntityFrameworkCore.Storage。Internal.RelationalCommandBuilderFactory:信息:已执行的 DbCommand (5ms) [Parameters=[@__id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u ].[CustRef], [u].[Email], [u].[EmailConfirmed], [u].[IsEnabled], [u].[LockoutEnabled], [u].[LockoutEnd], [u]。 [NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled ], [u].[UserName] FROM [AspNetUsers] AS [u] WHERE [u].[Id] = @__id_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@] __custRef_0='?' (大小 = 10)], CommandType='Text', CommandTimeout='30' ] SELECT TOP(1) [c].[CustomerDetailsId], [c].[CustRef], [c].[CustomerDBConnectionString], [c].[Enabled], [c].[Name], [c]。 [UserLicenses] FROM [CustomerDetails] AS [c] WHERE [c].[CustRef] = @__custRef_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__custRef_0='?' (Size = 10)], CommandType='Text', CommandTimeout='30'] SELECT [x].[ID], [x].[AspNetUserId], [x].[CustRef], [x].[CustomerId] ], [x].[Email], [x].[FirstName], [x].[IsEnabled], [x].[IsMaster], [x].[ShowCosts], [x].[Surname] FROM [用户] AS [x] WHERE [x].[CustRef] = @__custRef_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__users_Id_0='?'], CommandType='文本',CommandTimeout='30'] SELECT TOP(1) [a].[ID], [a].[AspNetUserId], [a].[CustRef], [a].[CustomerId], [a].[Email] , [a].[FirstName], [a].[IsEnabled], [a].[IsMaster], [a].[ShowCosts], [a].[Surname] FROM [Users] AS [a] WHERE [ a].[ID] = @__users_Id_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u ].[CustRef], [u].[Email], [u].[EmailConfirmed], [u].[IsEnabled], [u].[LockoutEnabled], [u].[LockoutEnd], [u]。 [NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled ], [u]。[UserName] FROM [AspNetUsers] AS [u] WHERE [u].[Id] = @__id_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u ].[CustRef], [u].[Email], [u].[EmailConfirmed], [u].[IsEnabled], [u].[LockoutEnabled], [u].[LockoutEnd], [u]。 [NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled ], [u].[UserName] FROM [AspNetUsers] AS [u] WHERE [u].[NormalizedUserName] = @__normalizedUserName_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: 执行 DbCommand (6ms) [Parameters=[@p16='?' (大小 = 450), @p0='?', @p1='?' (大小 = 4000), @p17='?' (大小 = 4000), @p2='?' (大小 = 4000), @p3='?' (大小 = 256), @p4='?', @p5='?', @p6='?', @p7='?', @p8='?' (大小 = 256), @p9='?' (大小 = 256), @p10='?' (大小 = 4000), @p11='?' (大小 = 4000), @p12='?', @p13='?' (大小 = 4000), @p14='?', @p15='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SET NOCOUNT ON; 更新 [AspNetUsers] SET [AccessFailedCount] = @p0, [ConcurrencyStamp] = @p1, [CustRef] = @p2, [Email] = @p3, [EmailConfirmed] = @p4, [IsEnabled] = @p5, [LockoutEnabled] = @p6, [LockoutEnd] = @p7, [NormalizedEmail] = @p8, [NormalizedUserName] = @p9, [PasswordHash] = @p10, [PhoneNumber] = @p11, [PhoneNumberConfirmed] = @p12, [SecurityStamp] = @p13, [TwoFactorEnabled] = @p14, [UserName] = @p15 WHERE [Id] = @p16 AND [ ConcurrencyStamp] = @p17; 选择@@ROWCOUNT; Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__menuId_0='?'], CommandType='Text', CommandTimeout='30'] SELECT [u].[CustomerMenuId], [u].[MenuItemId] FROM [CustomerMenuItem] AS [u] WHERE [u].[CustomerMenuId] = @__menuId_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[], CommandType ='Text', CommandTimeout='30'] SELECT [m].[Id], [m].[AspNetPolicyId], [m].[GlyphIcon], [m].[Label], [m]. [MenuGroupId] FROM [MenuItem] AS [m] Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[], CommandType='Text', CommandTimeout='30'] SELECT [a] .[Id], [a].[DefaultAction], [a].[Description], [a].[Name] FROM [AspNetPolicy] AS [a] Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [参数=[@__id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u ].[CustRef], [u].[Email], [u].[EmailConfirmed], [u].[IsEnabled], [u].[LockoutEnabled], [u].[LockoutEnd], [u]。 [NormalizedEmail], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u]。[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled], [u].[UserName] FROM [AspNetUsers] AS [u] WHERE [u].[Id] = @__id_0 Microsoft.EntityFrameworkCore。 Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__user_Id_0='?' (Size = 450)], CommandType='Text', CommandTimeout='30'] SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId ] FROM [AspNetUserClaims] AS [uc] WHERE [uc].[UserId] = @__user_Id_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (9ms) [Parameters=[@__8__locals1_user_Id_0='?' (大小 = 450),@__claim_Value_1='?' (大小 = 4000), @__claim_Type_2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30'] SELECT [uc]。[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId] FROM [AspNetUserClaims] AS [uc] WHERE (([uc].[UserId] = @__8__locals1_user_Id_0) AND ([uc].[ClaimValue] = @__claim_Value_1)) AND ([uc].[ClaimType] = @__claim_Type_2) Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (6ms) [Parameters=[@__8__locals1_user_Id_0= '?(大小 = 450),@__claim_Value_1='?' (大小 = 4000), @__claim_Type_2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30'] SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId] ] FROM [AspNetUserClaims] AS [uc] WHERE (([uc].[UserId] = @__8__locals1_user_Id_0) AND ([uc].[ClaimValue] = @__claim_Value_1)) AND ([uc].[ClaimType] = @__claim_Type_2) Microsoft.EntityFrameworkCore.Storage.Internal。RelationalCommandBuilderFactory:Information: Executed DbCommand (93ms) [Parameters=[@__8__locals1_user_Id_0='?' (大小 = 450), @__claim_Value_1='?' (大小 = 4000), @__claim_Type_2='?' (Size = 4000)], CommandType='Text', CommandTimeout='30'] SELECT [uc].[Id], [uc].[ClaimType], [uc].[ClaimValue], [uc].[UserId] ] FROM [AspNetUserClaims] AS [uc] WHERE (([uc].[UserId] = @__8__locals1_user_Id_0) AND ([uc].[ClaimValue] = @__claim_Value_1)) AND ([uc].[ClaimType] = @__claim_Type_2) Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (5ms) [Parameters=[@__normalizedUserName_0='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SELECT TOP(1) [u].[Id], [u].[AccessFailedCount], [u].[ConcurrencyStamp], [u ]。[CustRef], [u].[Email], [u].[EmailConfirmed], [u].[IsEnabled], [u].[LockoutEnabled], [u].[LockoutEnd], [u].[NormalizedEmail ], [u].[NormalizedUserName], [u].[PasswordHash], [u].[PhoneNumber], [u].[PhoneNumberConfirmed], [u].[SecurityStamp], [u].[TwoFactorEnabled], [u].[UserName] FROM [AspNetUsers] AS [u] WHERE [u].[NormalizedUserName] = @__normalizedUserName_0 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:Information: Executed DbCommand (6ms) [Parameters=[@p0= '?', @p1='?', @p2='?', @p19='?' (大小 = 450), @p3='?', @p4='?' (大小 = 4000), @p20='?' (大小 = 4000), @p5='?' (大小 = 4000), @p6='?' (大小 = 256), @p7='?', @p8='?', @p9='?', @p10='?', @p11='?' (大小 = 256), @p12='?' (大小 = 256), @p13='?' (大小 = 4000), @p14='?' (大小 = 4000), @p15='?', @p16='?' (大小 = 4000), @p17='?', @p18='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SET NOCOUNT ON; DELETE FROM [AspNetUserClaims] WHERE [Id] = @p0; 选择@@ROWCOUNT; DELETE FROM [AspNetUserClaims] WHERE [Id] = @p1; 选择@@ROWCOUNT; 从 [AspNetUserClaims] 中删除 [Id] = @p2; 选择@@ROWCOUNT; 更新 [AspNetUsers] SET [AccessFailedCount] = @p3, [ConcurrencyStamp] = @p4, [CustRef] = @p5, [Email] = @p6, [EmailConfirmed] = @p7, [IsEnabled] = @p8, [LockoutEnabled] = @p9, [LockoutEnd] = @p10, [NormalizedEmail] = @p11, [NormalizedUserName] = @p12, [PasswordHash] = @p13, [PhoneNumber] = @p14, [PhoneNumberConfirmed] = @p15, [SecurityStamp] = @p16, [TwoFactorEnabled] = @p17, [用户名] = @p18 WHERE [Id] = @p19 AND [ConcurrencyStamp] = @p20; 选择@@ROWCOUNT; “dotnet.exe”(CoreCLR:clrhost):加载“C:\Users\jsmith.nuget\packages\system.diagnostics.stacktrace\4.3.0\lib\netstandard1.3\System.Diagnostics.StackTrace.dll”。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.EntityFrameworkCore.DbContext:Error: 保存更改时数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 \Users\jsmith.nuget\packages\system.diagnostics.stacktrace\4.3.0\lib\netstandard1.3\System.Diagnostics.StackTrace.dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.EntityFrameworkCore.DbContext:Error: 保存更改时数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 \Users\jsmith.nuget\packages\system.diagnostics.stacktrace\4.3.0\lib\netstandard1.3\System.Diagnostics.StackTrace.dll'。跳过加载符号。模块已优化,调试器选项“仅我的代码”已启用。Microsoft.EntityFrameworkCore.DbContext:Error: 保存更改时数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 保存更改时数据库发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 保存更改时数据库发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 http://go.microsoft.com/fwlink/?LinkId=527962有关理解和处理乐观并发异常的信息。在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__6.MoveNext() 从上一个位置抛出异常的堆栈异常 --- 堆栈结束处- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__2.MoveNext() --- 堆栈跟踪结束从之前抛出异常的位置 --- 在 System.Runtime。

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。请参阅 http://go.microsoft.com/fwlink/?LinkId=527962有关理解和处理乐观并发异常的信息。在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__6.MoveNext() 从上一个位置抛出异常的堆栈异常 --- 堆栈结束处- 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.d__2.MoveNext() --- 堆栈跟踪结束从之前抛出异常的位置 --- 在 System.Runtime。EntityFrameworkCore.Storage.Internal.RelationalCommandBuilderFactory:信息:已执行的 DbCommand (6ms) [Parameters=[@p0='?', @p1='?', @p2='?', @p19='?' (大小 = 450), @p3='?', @p4='?' (大小 = 4000), @p20='?' (大小 = 4000), @p5='?' (大小 = 4000), @p6='?' (大小 = 256), @p7='?', @p8='?', @p9='?', @p10='?', @p11='?' (大小 = 256), @p12='?' (大小 = 256), @p13='?' (大小 = 4000), @p14='?' (大小 = 4000), @p15='?', @p16='?' (大小 = 4000), @p17='?', @p18='?' (Size = 256)], CommandType='Text', CommandTimeout='30'] SET NOCOUNT ON; DELETE FROM [AspNetUserClaims] WHERE [Id] = @p0; 选择@@ROWCOUNT; DELETE FROM [AspNetUserClaims] WHERE [Id] = @p1; 选择@@ROWCOUNT; 从 [AspNetUserClaims] 中删除 [Id] = @p2; 选择@@ROWCOUNT; 更新 [AspNetUsers] SET [AccessFailedCount] = @p3, [ConcurrencyStamp] = @p4, [CustRef] = @p5, [Email] = @p6, [EmailConfirmed] = @p7, [IsEnabled] = @p8, [LockoutEnabled] = @p9, [LockoutEnd] = @p10, [NormalizedEmail] = @p11, [NormalizedUserName] = @p12, [PasswordHash] = @p13, [PhoneNumber] = @p14, [PhoneNumberConfirmed] = @p15, [SecurityStamp] = @p16, [TwoFactorEnabled] = @p17, [UserName] = @p18 WHERE [Id] = @p19 AND [ConcurrencyStamp] = @p20; 选择@@ROWCOUNT; Microsoft.EntityFrameworkCore.DbContext:Error: 保存更改时数据库中发生异常。Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。看 http://go.microsoft.com/fwlink/?LinkId=527962了解有关理解和处理乐观并发异常的信息。在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagation.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagation.reader.Batch.Affected. ) 在 Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection) 在 Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable1 commandBatches, IRelationalConnection connection) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList1 个条目ToSave) 在Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess) 在Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess)

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException:数据库操作预期影响 1 行,但实际影响 0 行。自加载实体以来,数据可能已被修改或删除。请参阅 http://go.microsoft.com/fwlink/?LinkId=527962有关理解和处理乐观并发异常的信息。在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ThrowAggregateUpdateConcurrencyException(Int32 commandIndex, Int32 expectedRowsAffected, Int32 rowsAffected) 在 Microsoft.EntityFrameworkCore.Update.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagation.AffectedCountModificationCommandBatch.ConsumeResultSetWithoutPropagation.reader.Batch.Affected. ) 在 Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.Execute(IRelationalConnection connection) 在 Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.Execute(IEnumerable1 commandBatches, IRelationalConnection connection) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(IReadOnlyList1 entryToSave) 在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChanges(Boolean acceptAllChangesOnSuccess) 在 Microsoft.EntityFrameworkCore.DbContext.SaveChanges(Boolean acceptAllChangesOnSuccess) 抛出异常:'Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException' in Microsoft.EntityFrameworkCore.dll 线程已退出,代码为 0 (0x0)。线程 0xaa0 已退出,代码为 0 (0x0)。线程 0x6a84 已退出,代码为 0 (0x0)。

管理用户_更新:

    public async  Task<ActionResult> ManageUsers_Update([DataSourceRequest] DataSourceRequest request, ManageUsersViewModel viewModel)
    {
        if (viewModel != null && ModelState.IsValid)
        {
            User objToUpdate = new User
            {
                Id = viewModel.ID,
                FirstName = viewModel.FirstName,
                Surname = viewModel.Surname
            };
            _userRepository.UpdateUser(objToUpdate);

            if (viewModel.CustomerMenuId != null && viewModel.CustomerMenuId > 0)
            {
                int customerMenuId = Convert.ToInt32(viewModel.CustomerMenuId);

                // Update user's claims
                List<string> newClaims = _navigationRepository.GetPolicyNamesByCustomerMenuId(customerMenuId);
                bool claimsUpdated = await _applicationUserService.AssignClaimsToUser(viewModel.AspNetUserId, newClaims);

                // Assign user to menu if updating claims succeeded
                if (claimsUpdated)
                {
                    _navigationRepository.AssignCustomerMenuToUser(new CustomerMenuUser()
                        {CustomerMenuId = customerMenuId, AspNetUserId = viewModel.AspNetUserId});
                }
            }

            ApplicationUser user = await _userManager.FindByIdAsync(viewModel.AspNetUserId);
            user.IsEnabled = viewModel.IsEnabled;
            await _userManager.UpdateAsync(user);
        }

        return Json(new[] { viewModel }.ToDataSourceResult(request, ModelState));
    }
Run Code Online (Sandbox Code Playgroud)

Iva*_*uba 3

为什么会发生这种情况?

最可能的原因是并发冲突,这意味着多个用户(线程)尝试更改相同的数据。

在这里您可以找到有关其发生方式的更多详细信息

https://learn.microsoft.com/en-us/ef/core/ saving/concurrency

为了解决这个问题该怎么办?

我假设在您的情况下,多个用户不应该更新相同的声明,因此可能存在请求重复。

您可以尝试:

  • 检查数据库中的数据是否更新。如果有多个请求,其中一个应该保存更改;
  • 在发布请求时检查浏览器中的“网络”选项卡,或者放置一个断点并查看在单个请求期间命中了多少次;
  • 将有缺陷的代码与应用程序隔离并尝试重现该问题。

另一种方法(通常在允许多次访问时)是实施重试策略,以便在乐观失败的情况下重新执行更新逻辑。我很确定这不适合您的情况,但如果您需要快速解决方案,这将起作用。