Dab*_*rnl 2 batch-processing optimistic-concurrency entity-framework-4
Linq To SQL DataContext有一个重载,SubmitChanges它允许在抛出Optimistic Concurrency Exception时继续更新,并为开发人员提供一种机制,以便在一个Try Catch块中解决之后的冲突.
甚至它的方法也WCFDataServicesContext有一个SaveChangedOptions.ContinueOnError参数,它 SaveChanges至少允许你在发生错误时继续更新并且保留未解决的冲突更新,以便你以后可以查看它们.
(1)为什么ObjectContext.SaveChanges方法没有这样的选择?
(2)是否存在任何会模仿Linq To SQL行为的更新模式?我在MSDN上找到的示例使得看起来好像一个Try Catch块会在多次更新的情况下看到你回家.但是这种模式不允许您单独调查每个冲突的更新:它只是提醒您第一次冲突,然后为您提供"在一次扫描中擦除表清理"的选项,以防止任何进一步的乐观并发异常浮出水面,知道是否存在以及您希望如何处理它们.
那么为什么ObjectContext.SaveChanges方法没有这样的选项呢?
我认为最简单的答案是因为Linq-to-Sql,实体框架和WCF数据服务都是由不同的团队实施的,这些团队之间的内部沟通并不像我们希望的那样有效.我在之前的一个答案中描述了新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();
}
Run Code Online (Sandbox Code Playgroud)
我认为这个功能不存在的原因是因为它不是通用的,并且正如所提到的那样,它违背了工作单元模式.假设这个例子:
SqlException因为数据库中不存在主体.此异常将破坏持久性操作,您将不知道为什么它抱怨参照完整性,因为您有一个主体实体.(有可能这个插入甚至不会发生,并且由于上下文的内部状态不一致,EF会触发另一个异常,但这取决于EF的内部实现).这立即使整个放松冲突解决的功能更加复杂.恕我直言有三种解决方法:
这并不意味着它可能无法实现这样的功能,但它需要涵盖关系的所有场景,这可能相当复杂.我不确定Linq-to-Sql是否处理这个问题.
您可以随时在Data UserVoice上提出建议或查看代码并尝试自己实现.也许我觉得这个功能太复杂了,而且很容易实现.