我有这样的代码:
try
{
using (TransactionScope scope = new TransactionScope())
{
some_db_function();
for (i = 0; i < 10; i++)
{
some_other_db_function();
}
scope.Complete();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message + " all done transactions will rollback");
}
并在db函数内部发生这样的事情:
private void some_db_functions()
{
using (TransactionScope scope = new TransactionScope())
{
//some processing on db
scope.Complete();
}
}
假设数据库事务中存在任何问题,例如在函数中插入或更新错误;到目前为止已经完成的所有事务都被回滚。但它并不像那样工作;虽然它抛出异常并且父函数中的scope.Complete()
永远不会被触发,但仍然没有任何内容被回滚。
问题出在哪里?
答案 0 :(得分:14)
如果打开的连接已经存在,它将不会自动登记在环境事务中。你必须明确地设置它。
不支持隐式登记连接。参加一个 事务范围,您可以执行以下操作:
在事务范围内打开连接。
或者,如果连接已打开,请调用EnlistTransaction方法 在连接对象上。
这将招募现有连接:
connection.EnlistTransaction(Transaction.Current)
答案 1 :(得分:12)
他们都使用相同的连接,先前已声明
如果连接存在于事务之外,则不会登记。
最佳做法是仅在一个工作单元周围创建/打开连接,而不是永远(并且:让连接池完成其工作)。如果你遵循这种做法,它应该工作正常。所以:
这不起作用:
using(var conn = CreateAndOpenConnection()) {
// ...
using(var tran = new TransactionScope()) {
SomeOperations(conn);
tran.Complete();
}
// ...
}
在哪里 - 因为这应该有效:
using(var tran = new TransactionScope()) {
// ...
using(var conn = CreateAndOpenConnection()) {
SomeOperations(conn);
}
tran.Complete();
// ...
}