一. 什么是并发冲突?
在Web应用中, 当一个用户的更改还未提交时,另一用户更新同一数据会产生并发冲突.
二. 如何处理并发冲突
处理并发冲突的方法主要有两大类:
预防并发冲突的一种方法是使用数据库锁定。 这称为悲观并发。 应用在读取要更新的数据库行之前,将请求锁定。 锁定某一行的更新访问权限之后,其他用户在第一个锁定释放之前无法锁定该行。
缺点: 编程会比较复杂,并且随着用户增加可能会导致性能问题。 Entity Framework Core 未提供对它的内置支持,不推荐!
乐观并发允许发生并发冲突,并在并发冲突发生时作出正确反应。
如以下提交页面:

一个用户正准备修改Buget(预算)字段, 而同时另一个用户正提交日期字段的修改. 对于这种并发冲突有以下3种处理方式:
-
可以跟踪用户修改的属性,并仅更新数据库中相应的列
在这种情况下,数据不会丢失。 两个用户更新了不同的属性.
缺点: 无法避免数据丢失;对于 Web 应用。维持大量状态会影响应用性能;
可能会增加应用复杂性(与实体上的并发检测相比)。不推荐! -
客户端优先原则
也称"最后一个优先” , 客户端的所有值优先于数据存储的值。这是ASP.NET的默认处理原则 -
存储优先原则
数据存储值优先于客户端提交的值。
应用会:显示错误消息; 显示数据的当前状态; 允许用户重新应用更改。
三. 添加跟踪属性进行冲突检测
EF Core 在检测到冲突时会引发 DbConcurrencyException 异常。 数据模型必须配置为启用冲突检测。数据库表中增加一个跟踪更改时间的列。
对于 SQL Server 数据库,定义为byte[]的实体属性上应用 [Timestamp] 特性:
- 使列包含在 DELETE 和 UPDATE WHERE 子句中。
- 将数据库中的列类型设置为 rowversion。
数据库将生成有序的行版本号,该版本号随着每次行的更新递增。 在 Update 或 Delete 命令中,Where 子句包括提取的行版本值。 如果要更新的行在提交时发现:
- 当前的行版本值与提取值不相匹配。
- Update 或 Delete 命令不查找行,因为 Where 子句会查找提取行的版本值。
- 引发一个 DbUpdateConcurrencyException。
EF Core更新数据时生成的SQL语句如下
SET NOCOUNT ON;
UPDATE [Department] SET [Name] = @p0
WHERE [DepartmentID] = @p1 AND [RowVersion] = @p2;
SELECT [RowVersion]
FROM [Department]
WHERE @@ROWCOUNT = 1 AND [DepartmentID] = @p1;
代码显示包含 RowVersion 的 WHERE 子句。 如果数据库 RowVersion 不等于 RowVersion 参数 (@p2),则不更新行, 同时引发 DbUpdateConcurrencyException。
提交更改时, EF Core 会对比客户端与数据库中的RowVersion值, 如果不一致会触发DbUpdateConcurrencyException异常, 我们只要捕捉此异常并做相应处理即可!

本文探讨了Web应用中的并发冲突,详细介绍了悲观并发与乐观并发的概念,以及如何通过添加跟踪属性进行冲突检测,确保数据的一致性和完整性。
1325

被折叠的 条评论
为什么被折叠?



