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

Dyl*_*lan 6 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");   
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

问题出在哪儿?

Mit*_*eat 14

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

不支持隐式登记连接.要在事务范围中登记,您可以执行以下操作:

在事务范围中打开连接.

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

参考.

这将获得现有连接:

connection.EnlistTransaction(Transaction.Current)
Run Code Online (Sandbox Code Playgroud)


Mar*_*ell 12

IIRC,在连接创建/开放时自动进入环境事务; 如果你在事务范围内创建连接,那么一切都应该是好的.然而:

它们都使用之前声明的相同连接

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

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

这不起作用:

using(var conn = CreateAndOpenConnection()) {
    // ...
    using(var tran = new TransactionScope()) {
        SomeOperations(conn);
        tran.Complete();
    }
    // ...
}
Run Code Online (Sandbox Code Playgroud)

在哪里 - 因为这应该工作:

using(var tran = new TransactionScope()) {
    // ...
    using(var conn = CreateAndOpenConnection()) {
        SomeOperations(conn);
    }
    tran.Complete();
    // ...
}
Run Code Online (Sandbox Code Playgroud)