c# - asp.net 核心 : "Operations that change non-concurrent collections must have exclusive access."

标签 c# entity-framework asp.net-core mysql-connector

我的服务器使用 MySqlConnector 并与 AWS 上的 MySQL 数据库进行通信。我在 MySQL 中存储了 5 分钟的 API 计数器块。这些 API 计数器随着每次 API 调用而递增,并由 ConcurrentDictionary 代码处理(这似乎不是问题)。这行代码最近引发了一个异常,它是通过 MySqlConnector 访问 MySQL 数据库表的 linq 查询的一部分:
await _context.ApiCounts.Where(c => c.ApiName == apiName && c.StartTime >= startTime).ToListAsync();
我以前从未见过此行失败,但突然我的一台服务器开始在上面的行中抛出以下异常:

InvalidOperationException: Operations that change non-concurrent collections must have exclusive access. A concurrent update was performed on this collection and corrupted its state. The collection's state is no longer correct.
at System.ThrowHelper.ThrowInvalidOperationException_ConcurrentOperationsNotSupported
at System.Collections.Generic.Dictionary`2.FindEntry
at System.Collections.Generic.Dictionary`2.TryGetValue
at Remotion.Linq.Parsing.Structure.NodeTypeProviders.MethodInfoBasedNodeTypeRegistry.GetNodeType
at Remotion.Linq.Parsing.Structure.NodeTypeProviders.MethodInfoBasedNodeTypeRegistry.IsRegistered
at System.Linq.Enumerable.Any
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.GetQueryOperatorExpression
at Remotion.Linq.Parsing.ExpressionVisitors.SubQueryFindingExpressionVisitor.Visit
at System.Linq.Expressions.ExpressionVisitor.VisitBinary
at System.Linq.Expressions.BinaryExpression.Accept
at System.Linq.Expressions.ExpressionVisitor.VisitBinary
at System.Linq.Expressions.BinaryExpression.Accept
at System.Linq.Expressions.ExpressionVisitor.VisitLambda
at System.Linq.Expressions.Expression`1.Accept
at System.Linq.Enumerable+SelectListPartitionIterator`2.ToArray
at System.Linq.Enumerable.ToArray
at Remotion.Linq.Parsing.Structure.MethodCallExpressionParser.Parse
at Remotion.Linq.Parsing.Structure.ExpressionTreeParser.ParseMethodCallExpression
at Remotion.Linq.Parsing.Structure.QueryParser.GetParsedQuery
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileAsyncQueryCore
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler+<>c__DisplayClass24_0`1.<CompileAsyncQuery>b__0
at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQueryCore
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync
at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.System.Collections.Generic.IAsyncEnumerable<TResult>.GetEnumerator
at System.Linq.AsyncEnumerable+<Aggregate_>d__6`3.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at BlayFap.Controllers.ServerController+<GetCachedApiCount>d__13.MoveNext (E:\Projects\BlayFap\BlayFap\Controllers\ServerController.cs:342)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at BlayFap.Controllers.ServerController+<GetApiCount>d__14.MoveNext (E:\Projects\BlayFap\BlayFap\Controllers\ServerController.cs:378)
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeActionMethodAsync>d__12.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeNextActionFilterAsync>d__10.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next
at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker+<InvokeInnerFilterAsync>d__14.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeNextResourceFilter>d__22.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeFilterPipelineAsync>d__17.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification
at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker+<InvokeAsync>d__15.MoveNext
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw

所有其他表都可以正常访问,但从这里开始,任何使用 ApiCounts 表的尝试都会导致上述异常。我实际上必须重新启动受影响的服务器才能清除错误。看起来这个异常与对字典的并发编辑有关,并且该字典似乎在 linq 代码中。我猜测服务器可能陷入了这样一种情况,即 EF 在执行 linq 语句时同时更新和写入某种数据,然后让 Dictionary 陷入一种奇怪的状态,但我不知道如何防止这种情况以及真正的问题在哪里。这是 .NET 错误还是我自己的错误?

更多信息:我不修改此函数中 ApiCounts 的结果,也不调用 SaveChanges。但是,与此异步运行的代码(在另一个 REST 查询中)可以更新 ApiCounts 并调用 SaveChanges。

最佳答案

解决方案是更新到 EF 2.1.5 或更高版本。
发生此错误时,我正在使用 EF 2.0.3。看起来有一个线程不安全的单例,这可能会导致我看到的相同错误。这是github中的问题:https://github.com/dotnet/efcore/issues/12682

关于c# - asp.net 核心 : "Operations that change non-concurrent collections must have exclusive access.",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60690209/

相关文章:

asp.net-core - 替代 HttpResponse.ContentEncoding ASP.NET 5

c# - 鼠标滚轮在 winforms 中冒泡?

c# - 如何在 C# 中从 mongo 过滤时仅比较 dateTime 的日期?

c# - 在 C# 中从 SQL 数据库中读取值

c# - 无法检索项目元数据。确保这是一个基于MSBuild的.NET Core项目。 (迁移)

c# - 在 EF Core 中进行 SQL 跟踪期间丢失参数值

asp.net - 在数据访问层和业务层上实现哪种模式?

asp.net - 如何运行已发布的 Asp.Net core Web 应用程序

c# - exe之间的通信?

c# - 无法在列表框中找到所选项目 C# ASP.NET