Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/279.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 拥有的作用域对于并发DbContext访问是否是错误的解决方案?_C#_Entity Framework Core_Npgsql_Optimistic Locking_Optimistic Concurrency - Fatal编程技术网

C# 拥有的作用域对于并发DbContext访问是否是错误的解决方案?

C# 拥有的作用域对于并发DbContext访问是否是错误的解决方案?,c#,entity-framework-core,npgsql,optimistic-locking,optimistic-concurrency,C#,Entity Framework Core,Npgsql,Optimistic Locking,Optimistic Concurrency,当同一类的两个实例试图使用使用存储库的同一方法时,我在单例服务中遇到了这个错误 Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See

当同一类的两个实例试图使用使用存储库的同一方法时,我在单例服务中遇到了这个错误

Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException: Database operation expected to affect 1 row(s) but actually affected 0 row(s). Data may have been modified or deleted since entities were loaded. See http://go.microsoft.com/fwlink/?LinkId=527962 for information on understanding and handling optimistic concurrency exceptions.
   at Npgsql.EntityFrameworkCore.PostgreSQL.Update.Internal.NpgsqlModificationCommandBatch.ConsumeAsync(RelationalDataReader reader, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.ReaderModificationCommandBatch.ExecuteAsync(IRelationalConnection connection, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.Update.Internal.BatchExecutor.ExecuteAsync(DbContext _, ValueTuple`2 parameters, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(IReadOnlyList`1 entriesToSave, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.ChangeTracking.Internal.StateManager.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
   at Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(Boolean acceptAllChangesOnSuccess, CancellationToken cancellationToken)
为了解决这个问题,我在Autofac中找到了一个使用自有范围的解决方案

private readonly Func<Owned<IProductRepository>> productRepositoryFactory;
...
using (var repositoryOwned = productRepositoryFactory())
{
   await repositoryOwned.Value.DeleteRangeAsync(idsToRemove);
}
private readonly Func productRepositoryFactory;
...
使用(var repositoryOwned=productRepositoryFactory())
{
等待repositoryOwned.Value.DeleteRangeAsync(idsToRemove);
}
这解决了问题,但我担心性能会受到影响,因为DbContext的创建和处理(使用过的DbContext是按照依赖项注册的)。
对于这个问题,有没有更好的解决方案不会以这种方式影响性能?

如果计划将上下文传递给异步方法,则创建作用域是唯一的方法。例如,您可以在构造函数中为IServiceProvider serviceProvider使用DI,然后像这样使用它:

 using (var scope = _serviceProvider.CreateScope())
 {
     var service = scope.ServiceProvider.GetRequiredService<IYOURSERVICE>();
     ...
 }
使用(var scope=\u serviceProvider.CreateScope())
{
var service=scope.ServiceProvider.GetRequiredService();
...
}

没有并发DbContext访问。该类不适用于并发accesA DbContext也不是数据库连接。连接仅在需要时打开,即使如此,连接池也意味着在使用后立即关闭连接不会受到惩罚。相反,保持连接打开会导致延迟增加,因为在连接打开时获得的任何锁将一直保留到关闭为止。过了一段时间,连接开始相互冲突。现在我注意到实际的错误是
DbUpdateConcurrencyException:数据库操作预期影响1行,但实际影响0行。
这根本不是多线程或并发DbContext访问。它是关于乐观并发的。这意味着DbContext试图存储的行在此期间被修改。这是一个业务问题,AutoFac或任何类型的默认解决方案都无法解决。这类似于
git
冲突。您必须决定在这种情况下要做什么-覆盖修改?在某些情况下,这没关系。放弃您自己的更改?加载修改后的数据并检查哪些行已修改?可以安全地忽略对审核列的修改,如
ModifiedBy
。或者你应该问最终用户怎么做?EF核心文档解释了如何工作以及如何解决这些问题。目前的问题没有包含足够的信息来说明应该做什么。Autofac代码不相关。例外情况甚至没有提到实体。
产品
类是什么样子的,它是如何配置的?两个不同的连接最终如何修改同一个产品?这是一个有效的业务场景吗?两个用户可以打开同一个产品页面并更改描述或名称吗?例外情况与并发访问无关。它是关于乐观并发的