Entity framework 4 模式以克服缺少冲突模式的缺陷。是否在实体框架中继续冲突实现?
Linq To SQL的Entity framework 4 模式以克服缺少冲突模式的缺陷。是否在实体框架中继续冲突实现?,entity-framework-4,batch-processing,optimistic-concurrency,Entity Framework 4,Batch Processing,Optimistic Concurrency,Linq To SQL的DataContext在SubmitChanges上有一个重载,允许在抛出乐观并发异常时继续进行更新,并为开发人员提供了一种机制来解决以后的冲突 即使是WCFDataServicesContext也为其SaveChanges方法提供了一个SaveChangedOptions.ContinueOnError参数,该参数至少允许您在发生错误时继续更新,并使冲突的更新无法解决,以便您以后可以查看它们 (1) 那么为什么ObjectContext.SaveChanges方法没有这
DataContext
在SubmitChanges
上有一个重载,允许在抛出乐观并发异常时继续进行更新,并为开发人员提供了一种机制来解决以后的冲突
即使是WCFDataServicesContext
也为其SaveChanges
方法提供了一个SaveChangedOptions.ContinueOnError
参数,该参数至少允许您在发生错误时继续更新,并使冲突的更新无法解决,以便您以后可以查看它们
(1) 那么为什么ObjectContext.SaveChanges
方法没有这样的选项呢
(2) 是否存在模仿Linq到SQL行为的更新模式?我在MSDN上找到的例子使它看起来好像在多次更新的情况下会看到你回家。但这种模式不允许您单独调查每个冲突的更新:它只是提醒您第一个冲突,然后让您可以选择“一次扫描清除表”,以防止出现任何进一步的乐观并发异常,如果你不知道是否存在,以及你想对它们做些什么
那么为什么ObjectContext.SaveChanges方法没有这样的选项呢
我认为最简单的答案是因为LINQtoSQL、实体框架和WCF数据服务都是由不同的团队实现的,这些团队之间的内部通信并不像我们希望的那样有效。我已经在中描述了新API中缺少的一些有趣的特性,但我不认为这是一个缺少的特性-我将在回答的第二部分解释它
WCF数据服务具有更有趣的特性,这些特性也应该是实体框架的一部分。例如:
- 多个查询和SaveChanges操作可用于对服务器的单个调用
- -这将以异步/等待实现的形式出现在EF6中
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();
}
我认为这个特性不存在的原因是因为它不是泛型的,正如前面提到的,它违背了工作单元模式。假设这个例子:
- 加载一个实体
- 将新的从属实体添加到加载实体的导航属性中
- 在加载的实体上更改某些内容
- 同时,其他人会同时删除您加载的实体
- 您可以通过轻松的冲突解决方案触发SaveChanges
- EF将尝试保存对主体实体的更改,但会发生冲突,因为数据库中没有要更新的实体
- EF将继续,因为冲突解决变得轻松
- EF将尝试插入依赖实体,但它将触发
,因为数据库中不存在主体实体。此异常将破坏持久性操作,您将不知道为什么它会抱怨引用完整性,因为您有一个主体实体。(由于上下文的内部状态不一致,此插入甚至可能不会发生,EF引发另一个异常,但这取决于EF的内部实现)SqlException
- 根本不支持它。如果您需要每个实体的冲突解决方案,您仍然可以使用我上面展示的示例,但对于复杂场景,它可能不起作用,因为复杂场景很难解决
- 每次发生冲突时重新生成数据库更改集—这意味着探索剩余的更改集,并从已处理的持久性中排除与冲突实体及其关系相关的所有实体。存在一个问题:EF无法从处理中排除任何已更改的实体。这会破坏工作单位的意义,我再重复一次:放松冲突解决也会破坏工作单位的意义
- 让EF继续处理依赖项,即使主体实体发生冲突。这需要处理数据库异常并了解其内容,以了解异常是由于主体冲突还是由于其他错误(应立即使整个持久性操作失败)引发的。在代码级别上理解数据库异常可能非常困难,而且它对于每个受支持的数据库都是特定于提供者的