使用实体框架,大多数时间
SaveChanges()就足够了。这将创建一个事务,或加入任何环境事务,并在该事务中完成所有必要的工作。
尽管有时
SaveChanges(false) + AcceptAllChanges()配对很有用。
最有用的地方是要在两个不同的上下文之间进行分布式事务的情况。
即像这样(不好):
using (TransactionScope scope = new TransactionScope()){ //Do something with context1 //Do something with context2 //Save and discard changes context1.SaveChanges(); //Save and discard changes context2.SaveChanges(); //if we get here things are looking good. scope.Complete();}如果
context1.SaveChanges()成功但
context2.SaveChanges()失败,则整个分布式事务将中止。但是很遗憾,实体框架已经放弃了对的更改
context1,因此您无法重播或有效地记录故障。
但是,如果您将代码更改为如下所示:
using (TransactionScope scope = new TransactionScope()){ //Do something with context1 //Do something with context2 //Save Changes but don't discard yet context1.SaveChanges(false); //Save Changes but don't discard yet context2.SaveChanges(false); //if we get here things are looking good. scope.Complete(); context1.AcceptAllChanges(); context2.AcceptAllChanges();}在调用
SaveChanges(false)将必要的命令发送到数据库时,上下文本身不会更改,因此您可以在必要时再次进行操作,也可以根据需要进行询问
ObjectStateManager。
这意味着,如果事务实际上抛出异常,您可以通过在
ObjectStateManager某个地方重试或记录每个上下文的状态来进行补偿。
有关更多信息,请参见我的
博客文章。



