乐观并发:概述

LINQ to SQL 支持乐观并发控制。 下表介绍 LINQ to SQL 文档中适用于乐观并发的术语:

条款 DESCRIPTION
并发 当两个或多个用户同时尝试更新同一数据库行的情形。
并发冲突 (concurrency conflict) 当两个或多个用户同时尝试向一行的一个或多个列提交相互冲突的值时的情况。
并发控制 用于解决并发冲突的技术。
开放式并发控制 先调查其他事务是否已更改了行中的值,再允许提交更改的技术。

悲观并发控制形成对比,后者锁定记录以避免并发冲突。

之所以称作悲观控制,是因为它认为不可能发生一个事务干扰另一事务的情形。
冲突解决 通过再次查询数据库,然后协调差异来刷新冲突项的过程。

刷新对象时,LINQ to SQL 更改跟踪器包含以下数据:

- 最初从数据库获取并用于更新检查的值。
- 后续查询中的新数据库值。

LINQ to SQL 然后确定对象是否冲突(即一个或多个成员值是否已更改)。 如果对象处于冲突状态,LINQ to SQL 接下来将确定哪些成员存在冲突。

LINQ to SQL 发现的任何成员冲突将添加到冲突列表中。

在 LINQ to SQL 对象模型中,如果满足以下两个条件,则会发生 乐观并发冲突

  • 客户端尝试将更改提交到数据库。

  • 自客户端上次读取这些值以来,数据库中更新了一个或多个更新检查值。

解决此冲突包括发现对象的哪些成员存在冲突,然后决定如何处理冲突。

注释

只有映射为 AlwaysWhenChanged 的成员才会参与开放式并发检查。 不会对标记 Never的成员执行检查。 有关详细信息,请参阅 UpdateCheck

示例:

例如,在下面的情况中,User1 通过查询数据库中的某一行开始准备更新。 User1 接收到一行数据,其中的值为 Alfreds、Maria 和 Sales。

User1 希望将 Manager 列的值更改为 Alfred,将“部门”列的值更改为“市场营销”。 在 User1 提交这些更改之前,User2 已将更改提交到数据库。 因此,现在“助理”列的值已更改为“Mary”,“部门”列的值更改为“服务”。

当 User1 现在尝试提交更改时,提交将失败,并抛出ChangeConflictException异常。 之所以出现此结果,是因为“助理”列和“部门”列的数据库值不是预期的值。 表示 Assistant 和 Department 列的成员发生了冲突。 下表总结了情况。

国家 经理 助手 部门
原始状态 阿尔弗雷德斯 玛丽亚 销售额
User1 阿尔佛雷德 “营销”
User2 玛丽 服务

可以通过不同方式解决此类冲突。 有关详细信息,请参阅 “如何:管理更改冲突”。

冲突检测和解决清单

可以在任何详细级别检测和解决冲突。 在一种极端情况下,你可以以三种方式之一(见 RefreshMode)解决所有冲突,而无需考虑其他事项。 另一种极端情况是,您可以为发生冲突的每个成员上的每种冲突指定特定操作。

支持冲突发现和解决的 LINQ to SQL 类型

LINQ to SQL 中支持解决乐观并发冲突的类和功能包括:

另请参阅