C#回滚外部TransactionScope无论嵌套TransactionScopes中发生了什么

时间:2015-08-12 20:00:49

标签: c# sql-server transactions integration-testing transactionscope

首先,我已经阅读了这个类似的问题:Nested/Child TransactionScope Rollback但答案并没有提供解决方案,我们的问题略有不同。

基本上,我有一个使用事务范围的数据库集成测试(实际上,范围是在一个抽象类中的setup / teardown中管理)

[Test]
public void MyTest()
{
    using(var outerScope = new TransactionScope())
    {
        Assert.True(_myService.MyMethod());
        var values = _myService.AnotherMethod();
    }
}

MyService.MyMethod也使用TransactionScope

public bool MyMethod()
{
    using(var innerScope = new TransactionScope())
    using(var con = conFact.GetOpenConnection())
    {
        var cmd = con.CreateCommand();
        //set up and execute command
        if (isCheck) scope.Complete();
        return isCheck;
    }
}

所以理论上,如果isCheck为true,MyMethod只提交其更改,但无论该事务是否提交,在测试方法时,它都将被回滚。

除非isCheck为false,否则它按预期工作,在这种情况下,我得到以下异常:System.Transactions.TransactionException : The operation is not valid for the state of the transaction.

我认为这里发生的事情是,因为innerScope使用了TransactionScopeOption.Required,所以它加入了outerScope中使用的事务。当isCheck为false时,一旦innerScope被处理掉,那么outerScope也会被处理掉(这是我不希望发生的事情!)所以当我在调用MyMethod之后尝试获得另一个连接时,outerScope已经被处理掉了。

或者,如果我指定TransactionOption.RequiresNew,我会收到此异常:System.Data.SqlClient.SqlException : Timeout expired.

我尝试过使用带有指定保存点的SqlTransaction,以及TransactionOption的不同组合无济于事。

1 个答案:

答案 0 :(得分:2)

没有嵌套交易这样的东西。您可以嵌套作用域,但嵌套作用域所做的只是附加已在运行的事务。您不能独立于其他范围处理内部范围(当然除了RequiresNew,它只是创建一个独立的事务)。

IE11中不存在您想要的功能。

保存点是创建看起来像嵌套事务的东西的唯一方法。但是,SQL Server很容易因任意原因而终止您的整个事务。什么错误回滚语句以及哪些错误回滚事务是不可预测的。 (是的,这没有任何意义。)