.net NET中的嵌套事务

.net NET中的嵌套事务,.net,.net-4.0,transactions,sql-server-2008-r2,.net,.net 4.0,Transactions,Sql Server 2008 R2,我该如何执行类似的操作?但我想以其他方式实现同等目的: 业务逻辑类: public bool Bar() { try { using (var tsWork = new TransactionScope()) { ComplicatedDataImportCode(somedata); FlagRecordInDatabaseAsImported(); // this is the same record that's modified in th

我该如何执行类似的操作?但我想以其他方式实现同等目的:

业务逻辑类:

public bool Bar()
{
  try
  {
    using (var tsWork = new TransactionScope())
    {
      ComplicatedDataImportCode(somedata);
      FlagRecordInDatabaseAsImported(); // this is the same record that's modified in the catch
      tsWork.Complete();
      return true;
    }
    catch (DuplicateDataException err)
    {
      // if we got here, the above transaction should have rolled back,
      // so take that same record in the database and update it to "Duplicate".
      FlagSameRecordInDatabaseAsDuplicate(err.Message);
    }

    return false;
}
现在这一切都很好,直到我将所有这些封装在一个事务中(可能是一个我希望在执行断言后回滚的集成测试)

证明我观点的简单测试:

public void CanTest()
{
  // Arrange
  var foo = new Foo();

  using (var ts = new TransactionScope())
  {
    // Act
    var success = foo.Bar();

    // Assert
    if (success)
    {
      Assert.That(SomethingThatTestsThatTheDataWasImported);
    }
    else
    {
      Assert.That(SomethingThatTestsThatTheRecordWasMarkedAsDuplicate);
    }

    // Now that we have been able to perform our Asserts, rollback.

  }
}
最后,可以修改
Foo.Bar()
中的代码以适应解决方案,但是,不能为此解决方案修改
compleddataimportcode()
中的代码,因此,我确实需要确保在故障场景中正确回滚


同样,根据我在问题开头提到的帖子,我理解TransactionScopes不能用来做这件事。我在这里使用TransactionScope来表示我想要做什么,并且正在寻找实现此功能的最佳替代方法。

您使用的DBMS是否必须支持此功能

SQL Server并不真正支持嵌套事务,例如,您可以使用SQL Server


几年前我在我的博客上写过。

如果你能获得
compleddataimportcode
正在使用的活动数据库连接,你应该只需要在该连接上运行
BEGIN-TRAN
ROLLBACK-TRAN

SQL Server支持嵌套事务,只是第一次回滚会杀死所有级别<代码>提交遵守嵌套。嗯,也许我错误地理解了SQL Server支持这一点。我想了解更多。阅读你的链接+1目前…@Kratz:你的评论正是我的问题。我希望
ROLLBACK
只回滚特定的“内部事务”,而不是整个事务。我认为这确实是这个问题的答案。我想问另一个问题,这次是关于EF和保存点的。发抖谢谢,弗雷德里克!SQL Server支持嵌套事务是一种常见的误解。事实并非如此。打开多个事务,然后调用commit完全不起任何作用。您可以很容易地编写一些测试SQL来自己尝试。这里模拟嵌套事务的唯一选项是使用上面提到的保存点。但这不允许部分回滚。回滚会毁掉整个事务,这就是问题所在。如果我按照你说的做,那么当我执行回滚时,我对
flagsamerecordindabaseasduplicate
的调用将不起作用,因为当我的CanTest方法调用它时,它在同一个事务中。