实体框架6和悲观并发 [英] entity framework 6 and pessimistic concurrency

查看:90
本文介绍了实体框架6和悲观并发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在研究一个逐步淘汰旧应用程​​序的项目. 在过程中,作为临时解决方案,我们使用数据库与旧版应用程序集成.

I'm working on a project to gradually phase out a legacy application. In the proces, as a temporary solution we integrate with the legacy application using the database.

旧版应用程序使用具有可序列化隔离级别的事务. 由于数据库与遗留应用程序集成,因此我目前最好使用相同的悲观并发模型和可序列化的隔离级别.

The legacy application uses transactions with serializable isolation level. Because of database integration with a legacy application, i am for the moment best off using the same pessimistic concurrency model and serializable isolation level.

这些序列化的事务不仅应包含在SaveChanges语句周围,而且还应包括一些数据读取.

These serialised transactions should not only be wrapped around the SaveChanges statement but includes some reads of data as well.

我是通过

  • 围绕我的DbContext创建具有序列化隔离级别的transactionScope.
  • 创建DbContext
  • 读点书
  • 对对象进行一些更改
  • 在DbContext上调用SaveChanges
  • 提交事务范围(从而保存更改)

我的想法是,这会将我的整个读写操作包装在序列化事务中,然后提交.

I am under the notion that this wraps my entire reads and writes into on serialised transaction and then commits.

我认为这是悲观并发的一种方式.

I consider this a way form of pessimistic concurrency.

但是,请阅读本文, https://docs.microsoft.com/zh-cn/aspnet/mvc/overview/在asp-net-mvc应用程序中开始使用ef-using-mvc/使用实体框架处理并发 指出ef不支持悲观并发.

However, reading this article, https://docs.microsoft.com/en-us/aspnet/mvc/overview/getting-started/getting-started-with-ef-using-mvc/handling-concurrency-with-the-entity-framework-in-an-asp-net-mvc-application states that ef does not support pessimistic concurrency.

我的问题是:

  • A:EF是否支持我围绕读写操作使用可序列化事务的方式
  • B:在一个事务中包装读写操作可以保证提交事务时不会更改我的读取数据.
  • C:这是悲观并发的一种形式吗?

推荐答案

实现悲观并发的一种方法是使用类似以下的方法:

One way to acheive pessimistic concurrency is to use sonething like this:

var options = new TransactionOptions
{
   IsolationLevel = System.Transactions.IsolationLevel.Serializable,
   Timeout = new TimeSpan(0, 0, 0, 10)
};

using(var scope = new TransactionScope(TransactionScopeOption.RequiresNew, options))
{ ... stuff here ...}

在VS2017中,您似乎必须右键单击TransactionScope,然后获取它以添加以下引用:Reference Assemblies \ Microsoft \ Framework.NETFramework \ v4.6.1 \ System.Transactions.dll

In VS2017 it seems you have to rightclick TransactionScope then get it to add a reference for: Reference Assemblies\Microsoft\Framework.NETFramework\v4.6.1\System.Transactions.dll

但是,如果有两个线程尝试递增同一计数器,则会发现一个成功,而另一个线程在10秒内发出超时.这样做的原因是,当他们继续保存更改时,他们都需要将其锁升级为独占,但不能这样做,因为其他事务已经在同一行上持有共享锁.然后,SQL Server将在一段时间内使一个事务解决该死锁失败后检测到该死锁.失败的一个事务将释放共享锁,第二个事务将能够将其共享锁升级为排他锁并继续执行.

However if you have two threads attempt to increment the same counter, you will find one succeeds whereas the other thread thows a timeout in 10 seconds. The reason for this is when they proceed to saving changes they both need to upgrade their lock to exclusive, but they cannot because other transaction is already holding a shared lock on the same row. SQL Server will then detect the deadlock after a while fails one transactions to solve the deadlock. Failing one transaction will release shared lock and the second transaction will be able to upgrade its shared lock to exclusive lock and proceed with execution.

摆脱这种僵局的方法是使用诸如

The way out of this deadlocking is to provide a UPDLOCK hint to the database using something such as:

private static TestEntity GetFirstEntity(Context context) {
return context.TestEntities
              .SqlQuery("SELECT TOP 1 Id, Value FROM TestEntities WITH (UPDLOCK)")
              .Single();
}

此代码来自Ladislav Mrnka的博客,该博客现在似乎不可用.另一种选择是求助于乐观锁定.

This code came from Ladislav Mrnka's blog which now looks to be unavailable. The other alternative is to resort to optimistic locking.

这篇关于实体框架6和悲观并发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆