我是第一次尝试在C#中使用嵌套事务。在过去,我始终将SqlCommands
包裹在SqlTransactions
SqlConnections
内。像这样:
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块的事实不会回滚任何事务。
会感激一些帮助。下面是我的小测试应用程序的代码。
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");
答案 0 :(得分:2)
SqlConnection
在打开时会自行登记。只有这个时间点很重要。该连接将被登记到当时处于活动状态的任何事务中。您在安装任何事务之前打开连接。
我相信你有第二个误解:无法嵌套交易。您只能嵌套范围。回滚内部作用域时,将回滚整个事务。所有TransactionScope
都设置并操作Transaction.Current
。而已。最外面的作用域安装一个事务。内部范围大多是无操作。他们所做的就是提供一种通过不完成交易来完成交易的方法。