乐观并发:概述
LINQ to SQL 支持乐观并发控制。 下表介绍 LINQ to SQL 文档中适用于乐观并发的术语:
术语 | 说明 |
---|---|
concurrency | 两个或更多用户同时尝试更新同一数据库行的情形。 |
并发冲突 (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,将 Department 列的值更改为 Marketing。 在 User2 将更改提交到数据库后,User1 才能提交这些更改。 所以,现在 Assistant 列的值已更改为 Mary,Department 列的值已更改为 Service。
当 User1 现在尝试提交更改时,提交失败并且引发 ChangeConflictException 异常。 出现这种结果是因为 Assistant 列和 Department 列的数据库值并不是他们所预期的那些值。 表示 Assistant 和 Department 列的成员发生了冲突。 下表对这种情形作了总结。
状态 | Manager | Assistant | 部门 |
---|---|---|---|
原始状态 | Alfreds | Maria | Sales |
User1 | Alfred | Marketing | |
User2 | Mary | 服务 |
您可以用多种不同的方式来解决此类冲突。 有关详细信息,请参阅如何:管理更改冲突。
冲突检测和解决检查表
您可以检测和解决任意详细等级的冲突。 一种极端情况是,您可以用三种方式之一(请参见 RefreshMode)来解决所有冲突,而不再作其他方面的考虑。 另一种极端情况是,您可以为发生冲突的每个成员上的每种冲突指定特定操作。
在您的对象模型中指定或修改 UpdateCheck 选项。
有关详细信息,请参阅如何:指定针对并发冲突对哪些成员进行测试。
在对 SubmitChanges 的调用的 try/catch 块中,指定您希望在哪个点引发异常。
有关详细信息,请参阅如何:指定何时引发并发异常。
决定你希望检索的冲突详细信息量,并在 try/catch 块中包括相应的代码。
有关详细信息,请参阅如何:检索实体冲突信息以及如何:检索成员冲突信息。
在
try
/catch
代码中包含你希望解决所发现的各种冲突的方式。有关详细信息,请参阅如何:通过保留数据库值解决冲突、如何:通过覆盖数据库值解决冲突以及如何:通过与数据库值合并来解决冲突。
支持冲突发现和解决的 LINQ to SQL 类型
LINQ to SQL 中支持解决乐观并发冲突的类和功能包括: