c# - 嵌套 TransactionScope() 不会回滚

标签 c# sql transactions

我第一次尝试在 C# 中使用嵌套事务。过去,我总是将 SqlCommands 包装在 SqlConnections 内的 SqlTransactions 中。像这样的事情:

using (SqlConnection myCon = new SqlConnection(...))    
    using (SqlTransaction myTran = myCon.BeginTransaction())
    {
        using (SqlCommand myCom1 = new SqlCommand("...", myCon, myTran))
        {
            ...
        }       
        using (SqlCommand myCom2 = new SqlCommand("...", myCon, myTran))
        {
            ...
        }
        .
        .
        .
        myTran.Commit();
    }
}

所有这些,当然还有必要的 try...catch 处理,因此,如果 SqlTransaction 内的任何地方发生异常,我知道没有任何 >SqlCommands 将被提交。

所以我想尝试一下 TransactionScope,但它不起作用。这就是我正在做的事情;我有两笔交易,一笔接一笔,但都在外部交易内。根据表单上选中的复选框,代码会引发异常: 1. 在第一个内部事务提交之前,或者 2. 两个内部交易之间,或者 3. 在第二个内部事务提交之前,或者 4. 就在外部事务提交之前

我遇到的问题是,无论我勾选哪个复选框,代码都会像不存在任何事务一样执行。换句话说,我由于异常而跳出 try block 的事实不会回滚任何事务。

希望得到一些帮助。下面是我的小测试应用程序的代码。

try
{
    using (SqlConnection sqlConnection = new SqlConnection(connectionString))
    {
        sqlConnection.Open();

        using (TransactionScope transactionOuter = new TransactionScope())
        {
            using (TransactionScope transactionInner1 = new TransactionScope())
            {
                using (SqlCommand sqlCommand = new SqlCommand("INSERT INTO BasicTable (Value) VALUES ('Inside Inner Transaction 1')", sqlConnection))
                {
                    sqlCommand.ExecuteNonQuery();
                }

                if (checkBox_FailInner1.Checked)
                    throw (new Exception("Failed inside inner transaction 1"));

                transactionInner1.Complete();
            }

            if (checkBox_FailBetween.Checked)
                throw (new Exception("Failed between inner transactions"));

            using (TransactionScope transactionInner2 = new TransactionScope())
            {
                using (SqlCommand sqlCommand = new SqlCommand("INSERT INTO BasicTable (Value) VALUES ('Inside Inner Transaction 2')", sqlConnection))
                {
                    sqlCommand.ExecuteNonQuery();
                }

                if (checkBox_FailInnner2.Checked)
                    throw (new Exception("Failed inside inner transaction 2"));

                transactionInner2.Complete();
            }

            if (checkBox_FailOuter.Checked)
                throw (new Exception("Failed before outer transaction could commit"));

            transactionOuter.Complete();
        }
    }
}
catch (Exception exc)
{
    MessageBox.Show(exc.Message);
}

MessageBox.Show("Done");

最佳答案

SqlConnection 在打开时会自行登记。只有这个时间点很重要。该连接将被登记到当时处于事件状态的任何事务中。您将在安装任何事务之前打开连接。

我相信你有第二个误解:事务是不可能嵌套的。您只能嵌套范围。当您回滚内部作用域时,整个事务都会回滚。 TransactionScope 所做的一切就是设置和操作 Transaction.Current。而已。最外面的范围安装一个事务。内部作用域大多是无操作的。他们所做的只是提供了一种通过不完成交易来毁灭交易的方法。

关于c# - 嵌套 TransactionScope() 不会回滚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22707872/

相关文章:

spring - @Transactional 方面的建议可能吗?

c# - 如何使用 MAPI 获取 Outlook 联系人组?

c# - Parallel for each 循环不保存所有文件

mysql - 优化具有时区转换和按小时分组的Mysql查询

MySQL事务难题

java - 如何检测待处理的 JDO 事务?

c# - 重定向 cmd.exe 的输入/输出

c# - 访问继承成员

java.sql.SQLException : ORA-06502: PL/SQL: numeric or value error: character to number conversio 异常

sql - 我应该如何将短文本字符串存储到 SQL Server 数据库中?