我一直在研究交易和看来,他们照顾自己的EF只要我传递false到SaveChanges(),然后调用AcceptAllChanges(),如果没有错误:
false
SaveChanges()
AcceptAllChanges()
SaveChanges(false); // ... AcceptAllChanges();
如果出现问题怎么办?我不必回滚,或者一旦我的方法超出范围,交易是否结束?
在事务中途分配的所有intentiy列会如何处理?我想如果有人在我的坏事发生之前在我的事后添加了一条记录,那么这意味着将丢失一个Identity值。
有什么理由TransactionScope在我的代码中使用标准类吗?
TransactionScope
使用实体框架,大多数时间SaveChanges()就足够了。这将创建一个事务,或加入任何环境事务,并在该事务中完成所有必要的工作。
尽管有时SaveChanges(false) + AcceptAllChanges()配对很有用。
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,因此您无法重播或有效地记录故障。
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。
SaveChanges(false)
ObjectStateManager
这意味着,如果事务实际上抛出异常,您可以通过在ObjectStateManager某个地方重试或记录每个上下文的状态来进行补偿。
有关更多信息,请参见我的 博客文章。