TransactionScope是否与预先存在的连接一起使用?

时间:2012-02-13 09:11:58

标签: c# transactionscope

我有这样的代码:

try
{
    using (TransactionScope scope = new TransactionScope())
    {
        some_db_function();

        for (i = 0; i < 10; i++)
        {
            some_other_db_function();
        }

        scope.Complete();
    }
}
catch (Exception ex)
{
   MessageBox.Show(ex.Message + " all done transactions will rollback");   
}

并在db函数内部发生这样的事情:

private void some_db_functions()
{
    using (TransactionScope scope = new TransactionScope())
    {
       //some processing on db
       scope.Complete();
    }
}

假设数据库事务中存在任何问题,例如在函数中插入或更新错误;到目前为止已经完成的所有事务都被回滚。但它并不像那样工作;虽然它抛出异常并且父函数中的scope.Complete()永远不会被触发,但仍然没有任何内容被回滚。

问题出在哪里?

2 个答案:

答案 0 :(得分:14)

如果打开的连接已经存在,它将不会自动登记在环境事务中。你必须明确地设置它。

  

不支持隐式登记连接。参加一个   事务范围,您可以执行以下操作:

     

在事务范围内打开连接。

     

或者,如果连接已打开,请调用EnlistTransaction方法   在连接对象上。

Ref

这将招募现有连接:

connection.EnlistTransaction(Transaction.Current)

答案 1 :(得分:12)

IIRC,在连接创建/开放时自动进入环境事务;如果你创建交易范围内的连接,一切都应该是好的。但是:

  

他们都使用相同的连接,先前已声明

如果连接存在于事务之外,则不会登记。

最佳做法是仅在一个工作单元周围创建/打开连接,而不是永远(并且:让连接池完成其工作)。如果你遵循这种做法,它应该工作正常。所以:

这不起作用:

using(var conn = CreateAndOpenConnection()) {
    // ...
    using(var tran = new TransactionScope()) {
        SomeOperations(conn);
        tran.Complete();
    }
    // ...
}

在哪里 - 因为这应该有效:

using(var tran = new TransactionScope()) {
    // ...
    using(var conn = CreateAndOpenConnection()) {
        SomeOperations(conn);
    }
    tran.Complete();
    // ...
}