嵌套/子TransactionScope回滚
我试图嵌套TransactionScopes(.net 4.0),因为它将在SQL Server中嵌套事务,但它看起来像它们的操作不同。 我希望我的子事务能够在它们失败时回滚,但允许父事务决定是否提交/回滚整个操作。 问题是第一次完成时,事务回滚。 我意识到完成不同于承诺。
我试图做的一个大大简化的例子:
static void Main(string[] args)
{
using(var scope = new TransactionScope()) // Trn A
{
// Insert Data A
DoWork(true);
DoWork(false);
// Rollback or Commit
}
}
// This class is a few layers down
static void DoWork(bool fail)
{
using(var scope = new TransactionScope()) // Trn B
{
// Update Data A
if(!fail)
{
scope.Complete();
}
}
}
我不能使用Suppress或RequiresNew选项,因为Trn B依赖于Trn A插入的数据。如果我使用这些选项,则Trn B会被Trn A阻止。
任何想法如何让它起作用,或者甚至可以使用System.Transactions命名空间?
谢谢
你可能不会喜欢这个答案,但是...
在嵌套范围内投票
虽然嵌套作用域可以加入根作用域的环境事务,但在嵌套作用域中调用Complete并不会影响根作用域。 只有从根范围到最后一个嵌套范围的所有范围投票才能提交事务,才会提交事务。
(使用事务范围实现隐式事务)
不幸的是, TransactionScope
类没有提供任何机制(我知道)分离工作单元。 这是全部或没有。 你可以通过使用TransactionScopeOption.Suppress
来防止在特定的工作单元上发生任何TransactionScopeOption.Suppress
,但这可能不是你想要的,因为你将失去该范围内的任何东西的原子性。
使用TransactionScope
时,只有一个“环境” TransactionScope
。 一旦TransactionScope
被处置或者在没有Complete
被执行的情况下被收集,整个环境事务就会被回滚; 就是这样,游戏结束了。
实际上,SQL Server根本不支持真正的嵌套事务,虽然可以(尽管有点不直观)通过适当使用SAVE TRAN
语句来实现相同的最终结果。 如果您需要这种特殊行为,将这一逻辑重新实现为存储过程(或其中几个)可能是您的最佳选择。