我正在测试以了解嵌套事务的工作原理,并发现了这种令人不安和意外的行为。
using(TransactionScope otx = new TransactionScope())
using(SqlConnection conn1 = new SqlConnection("Server=S;Database=DB;Trusted_Connection=yes"))
using(SqlCommand cmd1 = conn1.CreateCommand())
{
conn1.Open();
cmd1.CommandType = CommandType.Text;
cmd1.CommandText = "INSERT INTO FP.ACLs (ChangeToken,ACL) VALUES (1,0x)";
cmd1.ExecuteNonQuery();
using(TransactionScope itx = new TransactionScope(TransactionScopeOption.RequiresNew))
using(SqlConnection conn2 = new SqlConnection("Server=S;Database=DB;Trusted_Connection=yes"))
using(SqlCommand cmd2 = conn1.CreateCommand())
{
conn2.Open();
cmd2.CommandType = CommandType.Text;
cmd2.CommandText = "INSERT INTO FP.ACLs (ChangeToken,ACL) VALUES (2,0x)";
cmd2.ExecuteNonQuery();
// we don't commit the inner transaction
}
otx.Complete(); // nonetheless, the inner transaction gets committed here and two rows appear in the database!
}
我看到了另一个问题,但解决方案不适用。
如果我不指定TransactionScopeOption.RequiresNew(即我没有使用嵌套事务,只是一个嵌套作用域),那么当内部作用域没有完成时整个事务会回滚,调用otx.Complete时会出错()。这可以。
但我当然不希望嵌套事务在未成功完成时被提交!有谁知道这里发生了什么以及我如何获得预期的行为?
数据库是 SQL Server 2008 R2。