Я проверял, как работают вложенные транзакции, и обнаружил это тревожное и неожиданное поведение.
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.