我已经苦苦挣扎了 2 天,为我的简单场景找到合适的解决方案。
场景我想
在 .Net Core Parallel 循环中完成多个数据库访问,该循环将在同一个数据库中插入多个项目。
var actions = new List<Action>();
actions.Add(() => { new DbContext.Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext.Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext.Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext.Set<TEntity>().Add(entity); });
Parallel.ForEach(actions, new ParallelOptions { MaxDegreeOfParallelism = 2 },
action =>
{
action();
});
已知限制
- EF Core 的 DBContext 不是线程安全的(我们需要在每个 trhead 中重新创建它们)
- MySQL 服务器不接受使用同一事务建立的 2 个连接
- 似乎我们无法将已经打开的连接传递给 DBContext
- EF Core 每次与数据库交互时都会在内部打开和关闭与数据库的连接
例外
当前不支持多个同时连接或在同一事务中具有不同连接字符串的连接。
在 MySql.Data.MySqlClient.MySqlConnection.Open() 在 Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable 在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.Open(Boolean errorsExpected) 在 Microsoft.EntityFrameworkCore.Storage.RelationalConnection.OpenDbConnection(Boolean errorsExpected)
1.Enumerator.BufferlessMoveNext(DbContext _, Boolean buffer) at Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable
1.Enumerator.MoveNext() 在 Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider._TrackEntities[TOut,TIn](IEnumerable1 results, QueryContext queryContext, IList
1 entityTrackingInfos, IList1 entityAccessors)+MoveNext() at Microsoft.EntityFrameworkCore.Query.Internal.LinqOperatorProvider.ExceptionInterceptor
1.EnumeratorExceptionInterceptor.MoveNext() 在 System.Collections.Generic.List1.AddEnumerable(IEnumerable
1 个可枚举)在 System.Linq.Enumerable.ToList[TSource](IEnumerable`1 源)的 CloseTheMonth.Backend.Data.Repositories.AccountUserRightRepository.ListAccounts(Guid userId) 在 C:\Work\GitHub\CloseTheMonth\Backend\CloseTheMonth。 Data\Repositories\AccountUserRightRepository.cs:C:\Work\GitHub\CloseTheMonth\Backend\CloseTheMonth.Services\AccountUserRightService.cs:CloseTheMonth.Backend.Services.AccountUserRightService.ListAccounts(Guid userId) 的第 44 行:CloseTheMonth.Backend 的第 53 行.Controllers.AppController.Init(字符串授权,AppInitRequest 请求)在 C:\Work\GitHub\CloseTheMonth\Backend\CloseTheMonth.Backend\Controllers\AppController.cs:line 101
反思...
如果我可以像这样在全局范围内打开一个连接,并将其传递给我的 DBContexts,那就可以了。但我检查了 EF Core 和 Pomelo 源代码,但没有找到实现类似目标的方法。
也许除了 Pomelo 之外的其他一些 EF Core MySQL 驱动程序可以做到这一点?
var actions = new List<Action>();
using (var conn = new MySqlConnection())
{
actions.Add(() => { new DbContext(conn).Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext(conn).Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext(conn).Set<TEntity>().Add(entity); });
actions.Add(() => { new DbContext(conn).Set<TEntity>().Add(entity); });
Parallel.ForEach(actions, new ParallelOptions { MaxDegreeOfParallelism = 2 },
action =>
{
action();
});
}
我将 MySQL 服务器 (8.0.22) 与 Pomelo.EntityFrameworkCore.MySql (2.1.4) 一起使用