MySql.Data.MySqlClient.MySqlException:重复条目

Posted

技术标签:

【中文标题】MySql.Data.MySqlClient.MySqlException:重复条目【英文标题】:MySql.Data.MySqlClient.MySqlException: Duplicate entry 【发布时间】:2019-10-16 10:59:58 【问题描述】:

如何从 .net 身份代码中获取此自动脚手架的重复条目错误:

        public async Task<IActionResult> OnPostAsync(string returnUrl = null)
        
            returnUrl = returnUrl ?? Url.Content("~/");
            if (ModelState.IsValid)
            
                var user = new ApplicationUser   UserName = Input.Email, Email = Input.Email ;
                var result = await _userManager.CreateAsync(user, Input.Password);
                if (result.Succeeded)
                
                    _logger.LogInformation("User created a new account with password.");

                    var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                    var callbackUrl = Url.Page(
                        "/Account/ConfirmEmail",
                        pageHandler: null,
                        values: new  userId = user.Id, code = code ,
                        protocol: Request.Scheme);

                    await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                        $"Please confirm your account by <a href='htmlEncoder.Default.Encode(callbackUrl)'>clicking here</a>.");

                    await _signInManager.SignInAsync(user, isPersistent: false);
                    return LocalRedirect(returnUrl);
                
                foreach (var error in result.Errors)
                
                    ModelState.AddModelError(string.Empty, error.Description);
                
            

            // If we got this far, something failed, redisplay form
            return Page();
        

产生这个堆栈跟踪:

Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware[1] 执行请求时发生未处理的异常。 Microsoft.EntityFrameworkCore.DbUpdateException:更新条目时出错。有关详细信息,请参阅内部异常。 ---> '3ab1a765-c575-4a50-ba42-6d282ccb24a6' 键 'PRIMARY' ---> '3ab1a765-c575-4a50 -ba42-6d282ccb24a6' 用于键 'PRIMARY' 在 mysqlConnector.Core.ServerSession.TryAsyncContinuation(Task1 task) in C:\projects\mysqlconnector\src\MySqlConnector\Core\ServerSession.cs:line 1252 at System.Threading.Tasks.ContinuationResultTaskFromResultTask2.InnerInvoke() 在 System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext,ContextCallback 回调,对象状态) --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 System.Threading.Tasks.Task.ExecuteWithThreadLocal(任务和 currentTaskSlot) --- 从先前抛出异常的位置结束堆栈跟踪 --- 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\ResultSet.cs:line 43 中的 MySqlConnector.Core.ResultSet.ReadResultSetHeaderAsync(IOBehavior ioBehavior) --- 内部异常堆栈跟踪结束 --- 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 81 中的 MySql.Data.MySqlClient.MySqlDataReader.ActivateResultSet(ResultSet resultSet) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs:line 307 中的 MySql.Data.MySqlClient.MySqlDataReader.ReadFirstResultSetAsync(IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\MySql.Data.MySqlClient\MySqlDataReader.cs: 中的 MySql.Data.MySqlClient.MySqlDataReader.CreateAsync(MySqlCommand 命令,CommandBehavior 行为,ResultSetProtocol resultSetProtocol,IOBehavior ioBehavior) 在 C:\projects\mysqlconnector\src\MySqlConnector\Core\TextCommandExecutor.cs: 中的 MySqlConnector.Core.TextCommandExecutor.ExecuteReaderAsync(String commandText, MySqlParameterCollection parameterCollection, CommandBehavior 行为, IOBehavior ioBehavior, CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.Storage.Internal.RelationalCommand.ExecuteAsync(IRelationalConnection 连接,DbCommandMethod 执行方法,IReadOnlyDictionary2 parameterValues, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) --- End of inner exception stack trace --- at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple2 参数,CancellationToken 取消令牌) 在 Pomelo.EntityFrameworkCore.MySql.Storage.Internal.MySqlExecutionStrategy.ExecuteAsync[TState,TResult](TState 状态,Func4 operation, Func4 verifySucceeded,CancellationToken cancelToken) 在 Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList1 entriesToSave, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken) at Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore9.CreateAsync(TUser 用户,CancellationToken cancelToken) 在 Chuchubi.Data.MultiTenant.TenantUserStore.CreateAsync(ApplicationUser user, CancellationToken cancelToken) 在 C:\Users\Dropbox\Code\chuchubi-backend\Chuchubi.Data\MultiTenant\TenantUserStore.cs:line 30 在 Microsoft.AspNetCore.Identity.UserManager1.CreateAsync(TUser user) at Microsoft.AspNetCore.Identity.UserManager1.CreateAsync(TUser 用户,字符串密码) 在 Chuchubi.Areas.Identity.Pages.Account.RegisterModel.OnPostAsync(String returnUrl) 在 C:\Users\Dropbox\Code\chuchubi-backend\Chuchubi\Areas\Identity\Pages\Account\Register.cshtml.cs:line 71 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory.GenericTaskHandlerMethod.Convert[T](对象 taskAsObject) 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.ExecutorFactory.GenericTaskHandlerMethod.Execute(对象接收器,对象 [] 参数) 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeHandlerMethodAsync() 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeNextPageFilterAsync() 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Rethrow(PageHandlerExecutedContext 上下文) 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.Next(状态和下一个,范围和范围,对象和状态,布尔值和已完成) 在 Microsoft.AspNetCore.Mvc.RazorPages.Internal.PageActionInvoker.InvokeInnerFilterAsync() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext 上下文) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(状态&下一个,范围&范围,对象&状态,布尔& isCompleted) 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync() 在 Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync() 在 Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext 上下文) 在 SaasKit.Multitenancy.Internal.TenantResolutionMiddleware1.Invoke(HttpContext context, ITenantResolver1 tenantResolver) 在 Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.MigrationsEndPointMiddleware.Invoke(HttpContext 上下文) 在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore.DatabaseErrorPageMiddleware.Invoke(HttpContext httpContext) 在 Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext 上下文) 信息:Microsoft.AspNetCore.Hosting.Internal.WebHost[2]

这是来自 Visual Studio 自动生成的代码。

编辑:

MySql 版本详情:

'immediate_server_version', '999999'
'innodb_version', '8.0.16'
'original_server_version', '999999'
'protocol_version', '10'
'slave_type_conversions', ''
'tls_version', 'TLSv1,TLSv1.1,TLSv1.2'
'version', '8.0.16'
'version_comment', 'MySQL Community Server - GPL'
'version_compile_machine', 'x86_64'
'version_compile_os', 'Win64'
'version_compile_zlib', '1.2.11'

我的 csproj:

    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.2.4" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.3" />
    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.2.0" />
    <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" />
    <PackageReference Include="SaasKit.Multitenancy" Version="1.1.4" />

这是在空数据库上完成的,错误后没有用户被插入数据库!

【问题讨论】:

奇怪了,数据库里有3ab1a765-c575-4a50-ba42-6d282ccb24a6的记录吗?与我们分享Startup.csApplicationUser还有其他操作吗?如果新建一个空数据库,会不会出现这个问题? 嗨@TaoZhou 哦,是的,我忘了说,我在一个空数据库上执行此操作,并且没有添加任何用户! 如果有,好像和你的代码有关,有没有demo项目可以重现你的问题? 我稍后会尝试做一个! @TaoZhou 有链接我会标记你的 你是如何定义身份表的? 【参考方案1】:

好的,尝试在一个干净的项目中复制它,我设法弄明白了。 因此应用程序是多租户的,每个身份用户与租户之间存在一对一的关系。

使用 SaasKit 我将数据库模型 Tenant 缓存到内存中,同时像这样创建一个新用户:

IdentityUser.Tenant = cachedTenant;
DbContext.SaveChanges();

Entityframework 将租户视为新租户(未被跟踪),因此导致重复消息。

所以重复的消息实际上是给新租户的。

通过缓存“视图模型”而不是数据库模型来修复。

【讨论】:

以上是关于MySql.Data.MySqlClient.MySqlException:重复条目的主要内容,如果未能解决你的问题,请参考以下文章