LINQ to SQL 支持乐观并发控制。 下表介绍 LINQ to SQL 文档中适用于乐观并发的术语:
条款 | DESCRIPTION |
---|---|
并发 | 当两个或多个用户同时尝试更新同一数据库行的情形。 |
并发冲突 (concurrency conflict) | 当两个或多个用户同时尝试向一行的一个或多个列提交相互冲突的值时的情况。 |
并发控制 | 用于解决并发冲突的技术。 |
开放式并发控制 | 先调查其他事务是否已更改了行中的值,再允许提交更改的技术。 与 悲观并发控制形成对比,后者锁定记录以避免并发冲突。 之所以称作悲观控制,是因为它认为不可能发生一个事务干扰另一事务的情形。 |
冲突解决 | 通过再次查询数据库,然后协调差异来刷新冲突项的过程。 刷新对象时,LINQ to SQL 更改跟踪器包含以下数据: - 最初从数据库获取并用于更新检查的值。 - 后续查询中的新数据库值。 LINQ to SQL 然后确定对象是否冲突(即一个或多个成员值是否已更改)。 如果对象处于冲突状态,LINQ to SQL 接下来将确定哪些成员存在冲突。 LINQ to SQL 发现的任何成员冲突将添加到冲突列表中。 |
在 LINQ to SQL 对象模型中,如果满足以下两个条件,则会发生 乐观并发冲突 :
客户端尝试将更改提交到数据库。
自客户端上次读取这些值以来,数据库中更新了一个或多个更新检查值。
解决此冲突包括发现对象的哪些成员存在冲突,然后决定如何处理冲突。
注释
只有映射为 Always 或 WhenChanged 的成员才会参与开放式并发检查。 不会对标记 Never的成员执行检查。 有关详细信息,请参阅 UpdateCheck。
示例:
例如,在下面的情况中,User1 通过查询数据库中的某一行开始准备更新。 User1 接收到一行数据,其中的值为 Alfreds、Maria 和 Sales。
User1 希望将 Manager 列的值更改为 Alfred,将“部门”列的值更改为“市场营销”。 在 User1 提交这些更改之前,User2 已将更改提交到数据库。 因此,现在“助理”列的值已更改为“Mary”,“部门”列的值更改为“服务”。
当 User1 现在尝试提交更改时,提交将失败,并抛出ChangeConflictException异常。 之所以出现此结果,是因为“助理”列和“部门”列的数据库值不是预期的值。 表示 Assistant 和 Department 列的成员发生了冲突。 下表总结了情况。
国家 | 经理 | 助手 | 部门 |
---|---|---|---|
原始状态 | 阿尔弗雷德斯 | 玛丽亚 | 销售额 |
User1 | 阿尔佛雷德 | “营销” | |
User2 | 玛丽 | 服务 |
可以通过不同方式解决此类冲突。 有关详细信息,请参阅 “如何:管理更改冲突”。
冲突检测和解决清单
可以在任何详细级别检测和解决冲突。 在一种极端情况下,你可以以三种方式之一(见 RefreshMode)解决所有冲突,而无需考虑其他事项。 另一种极端情况是,您可以为发生冲突的每个成员上的每种冲突指定特定操作。
在对象模型中指定或修改 UpdateCheck 选项。
有关详细信息,请参阅如何:指定针对并发冲突对哪些成员进行测试。
在对 SubmitChanges 的调用的 try/catch 块中,指定您希望在哪个点引发异常。
有关详细信息,请参阅如何:指定何时引发并发异常。
确定您希望检索的详细冲突信息,并根据需要在 try/catch 块中添加相应的代码。
有关详细信息,请参阅 如何检索实体冲突信息 和 如何检索成员冲突信息。
在
try
/catch
代码中包含你希望解决所发现的各种冲突的方式。有关详细信息,请参阅 如何:通过保留数据库值解决冲突、 如何:通过覆盖数据库值解决冲突, 以及如何:通过合并数据库值解决冲突。
支持冲突发现和解决的 LINQ to SQL 类型
LINQ to SQL 中支持解决乐观并发冲突的类和功能包括: