Entity Framework的悲观并发控制

4
在我的项目中,用户可以根据需要编辑一些数据集。但是由于项目规范,一次只能有一个用户编辑某个数据集/访问该数据集的编辑页面。因此,如果用户A正在编辑Data Set 1,那么只要用户A在该页面,用户B就不能访问Data Set 1的编辑页面,反之亦然。
我进行了一些阅读,似乎悲观并发是我要寻找的内容,其中一个页面被“锁定”,直到页面内的用户离开,这解释了我的标题。
我对ASP.NET和Web开发仍然比较新。我想问一下,我是否朝着正确的方向解决了我的问题,如何在我的项目中实现它(我只看到了乐观并发的示例),是否有其他方法来处理我的问题,而我尚未遇到?

悲观并发应该不被使用,如果一个人不完全理解它是什么(在复杂操作的整个过程中保持事务打开),因为它会严重降低性能,因为它会阻塞任何试图影响锁定行的查询。在您的情况下,您正在描述一个可以使用行标志或签入/签出表来实现的签入/签出场景,而不是并发场景。甚至在Web应用程序中也不可能保持数据库事务处于打开状态-加载编辑页面和提交更改是不同的请求。 - Panagiotis Kanavos
1个回答

5
首先,我要说的是你的问题与数据库和EF有关,而不是ASP.NET MVC。顺便提一下,有两种基本类型的并发控制:
悲观并发:在用户请求数据时将其锁定,在他保存更改之前,其他用户无法在同一时间保存相同的数据。
乐观并发:不锁定任何东西,并假设第二个用户尝试更改数据时不会与第一个用户保存的更改冲突,但如果存在冲突,则放弃第二个用户的更改,只保留第一个用户的更改。
EF不直接支持悲观并发。
所以我认为最好的选择是乐观并发,EF支持这种方式,正如你可能知道的那样,它通过检查更新前后的数据来确定用户B是否在用户A检索和更新数据之间修改了它。如果更改了,则放弃用户A的修改,反之,则将用户A的修改更新到数据库中。
为了实现乐观并发,您可以简单地为您的模型定义一个RowVersion属性:
public byte[] RowVersion { get; set; }

在您的模型配置中,您应该告诉EF它在属性上具有行版本的行为:
Property(p => p.RowVersion).IsRowVersion();

现在,如果用户A检索了数据,并且用户B检索了相同的数据并且在用户A保存更改之前保存了更改,则会放弃用户A的更改并抛出异常:

存储更新、插入或删除语句影响了意外数量的行(0)。自从加载实体以来,实体可能已被修改或删除。刷新YourModelName条目。

更多信息


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接