Linq To SQL的DataContext
在SubmitChanges
上有一个重载,它允许在抛出Optimistic Concurrency Exception时继续更新,并为开发人员提供一种机制来解决之后{{3 }}。
即使WCFDataServicesContext
的{{1}}方法都有一个SaveChangedOptions.ContinueOnError
参数,至少可以让您在发生错误时继续更新并保留未解决的冲突更新,以便您可以查看它们后面。
(1)为什么SaveChanges
方法没有这样的选项?
(2)是否存在任何会模仿Linq To SQL行为的更新模式?我在MSDN上找到的示例使得看起来好像a single Try Catch block会在多次更新的情况下看到您回家。但是这种模式不允许您单独调查每个冲突的更新:它只是提醒您第一次冲突,然后为您提供“在一次扫描中擦除表清理”的选项,以防止任何进一步的乐观并发异常浮出水面,知道是否存在以及你想对它们做些什么。
答案 0 :(得分:5)
为什么ObjectContext.SaveChanges方法没有这样的选项?
我认为最简单的答案是因为Linq-to-Sql,实体框架和WCF数据服务都是由不同的团队实施的,这些团队之间的内部沟通并不像我们希望的那样有效。我已经描述了one of my former answers中较新的API中缺少的一些有趣的功能,但我不认为这是一个缺失的功能 - 我将在我的答案的第二部分解释它。
WCF数据服务具有更多有趣的功能,这些功能也应该是实体框架的一部分。例如:
是否存在任何会模仿Linq To SQL行为的更新模式?
有一种模式如何解决这个问题,但你可能不喜欢它。 EF的SaveChanges
作为工作单位。它保存所有更改或不保存。如果您有一个场景,您的保存操作可能会导致仅保留部分更改,而不应通过单个SaveChanges
调用处理。每个原子变更都应该有自己的SaveChanges
调用:
using (var scope = new TransactionScope(...)) {
foreach (var entity in someEntitiesToModify) {
try {
context.SomeEntities.Attach(entity);
context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified);
context.SaveChanges();
catch (OptimisticConcurrencyException e) {
// Do something here
context.Refresh(e.StateEntries[0].Entity, RefreshMode.ClientWins);
context.SaveChanges();
}
}
scope.Complete();
}
我认为这个功能不存在的原因是因为它不是通用的,并且正如所提到的那样,它违背了工作单元模式。假设这个例子:
SqlException
,因为数据库中不存在主体。此异常将破坏持久性操作,您将不知道为什么它抱怨参照完整性,因为您有一个主体实体。 (有可能这个插入甚至不会发生,EF由于上下文的内部状态不一致而引发另一个异常,但它依赖于EF的内部实现)。这使冲突解决的整个放松更加复杂。恕我直言有三种解决方法:
这并不意味着它可能无法实现这样的功能,但它需要涵盖关系的所有场景,这可能相当复杂。我不确定Linq-to-Sql是否处理这个问题。
您可以随时在Data UserVoice或check out the code上提出建议并尝试自行实施。也许我觉得这个功能太复杂了,而且很容易实现。