在Entity Framework中使用2个DbContext回滚事务,应该使用TransactionScope还是TransactionBegin?

7

我有两个 DbContext,我在一个表单中同时调用它们,如下所示:

    dbcontext1.add(object);
    dbcontext1.save();
    dbcontext2.add(object);
    dbcontext2.save();

所以我有一个问题:如果出现一些问题,我的记录由DbContext1保存但不在DbContext2中,我需要回滚事务。
我搜索了一下,发现有两种方法:使用BeginTransactionTransactionScope。我对该使用哪个方法以及它们之间的区别感到困惑?
我发现像这样的东西,但我不知道如何回滚它:
using (TransactionScope scope = new TransactionScope())  
{
  using (EFEntities1 dc = new EFEntities1())
  {
     dc.USERS.Add(user);
     dc.SaveChanges();
  }

  using (EFEntities2 dc = new EFEntities2())
  {
     dc.USERS.Add(user);
     dc.SaveChanges();
  }

  scope.complete();
}

最好的问候

1个回答

9
我不确定我应该使用哪个,它们之间有什么区别?
TransactionScope的区别在于,在单个数据库连接(SQL Server 2005)或在同一数据库上使用多个连接(SQL Server 2008及更高版本)时,它就像常规的轻量级和本地事务一样。如果两个或多个连接在同一个事务范围内使用,或者访问了多个数据库(取决于SQL Server版本),则它将升级为分布式事务(因此在MSDTC中注册)。在您的情况下,它将被提升。
我发现了这样的东西,但我不知道如何回滚。
只要不调用Complete,事务范围就会在范围结束时(例如,dispose,using结束等)回滚。
如果任何一个db上下文引发异常,则在您的代码中不会调用Complete,事务将被回滚。
来自MSDN:
如果在事务范围内没有发生异常(即在TransactionScope对象的初始化和调用其Dispose方法之间),则允许参与范围的事务继续进行。如果在事务范围内发生异常,则将回滚它参与的事务。
这也是为什么不存在Rollback方法的原因。
您可能还想查看要使用的隔离级别。默认值为Serializable。

谢谢亲爱的朋友,但我认为如果出现错误,它不会回滚您的事务。 - Ehsan Akbar
你的意思是如果错误发生在我的范围内,它默认会回滚? - Ehsan Akbar
1
@EA:对于TransactionScopes,是的。当抛出异常时,它会自动回滚(只要您不处理它并调用Complete)。请参见更新内容以及此链接:http://msdn.microsoft.com/zh-cn/library/system.transactions.transactionscope(v=vs.110).aspx。 - Marcel N.
这太棒了,我现在才发现它...晚了好几年。我一直试图使用多种方法,但如果其中一个失败,所有的东西都需要回退,我一直很苦恼。这看起来非常不错! - Piotr Kula

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接