【问题标题】:C# Rollback Outer TransactionScope Regardless of What Happens In Nested TransactionScopes无论嵌套的 TransactionScope 中发生什么,C# 都回滚外部 TransactionScope
【发布时间】:2015-08-12 20:00:49
【问题描述】:

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

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

[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;
    }
}

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

除非 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 组合无济于事。

【问题讨论】:

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


    【解决方案1】:

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

    System.Transactions 中不存在您想要的功能。

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

    【讨论】:

      猜你喜欢
      • 2011-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多