我第一次尝试在 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/