我正在尝试像在 SQL Server 中嵌套事务一样嵌套事务范围 (.net 4.0),但它们的操作方式似乎不同.我希望我的子事务在失败时能够回滚,但允许父事务决定是否提交/回滚整个操作.问题是当第一次完成时,事务被回滚.我意识到完成与提交不同.
I am trying to nest TransactionScopes (.net 4.0) as you would nest Transactions in SQL Server, however it looks like they operate differently. I want my child transactions to be able to rollback if they fail, but allow the parent transaction to decide whether to commit/rollback the whole operation. The problem is when the first complete occurs, the transaction is rolled back. I realize that complete is different to commit.
我正在尝试做的一个大大简化的例子:
A greatly simplified example of what I am trying to do:
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 阻止.
I can't use the Suppress or RequiresNew options as Trn B relies on data inserted by Trn A. If I do use those options, Trn B is blocked by Trn A.
任何想法如何让它工作,或者甚至可以使用 System.Transactions 命名空间?
Any ideas how I would get it to work, or if it is even possible using the System.Transactions namespace?
谢谢
您可能不会喜欢这个答案,但是...
You're probably not going to like this answer, but...
在嵌套范围内投票
虽然嵌套作用域可以加入根作用域的环境事务,但是在嵌套作用域中调用Complete对根作用域没有影响.只有从根作用域到最后一个嵌套作用域的所有作用域都投票提交事务,才会提交事务.
Although a nested scope can join the ambient transaction of the root scope, calling Complete in the nested scope has no affect on the root scope. Only if all the scopes from the root scope down to the last nested scope vote to commit the transaction, will the transaction be committed.
(来自 使用事务范围实施隐式事务)
TransactionScope
类很遗憾没有提供任何机制(据我所知)来隔离工作单元.要么全有要么全无.您可以使用 TransactionScopeOption.Suppress
来防止在特定工作单元上发生任何 事务,但这可能不是您想要的,因为您将失去原子性在那个范围内.
The TransactionScope
class unfortunately doesn't provide any mechanism (that I know of) for segregating units of work. It's all or nothing. You can prevent any transaction from occurring on a specific unit of work by using TransactionScopeOption.Suppress
, but that is probably not what you want, as you would then lose atomicity for whatever is inside that scope.
只有一种环境"使用 TransactionScope
时的交易.一旦 TransactionScope
在没有执行 Complete
的情况下被释放或收集,整个环境事务将被回滚;就这样,游戏结束.
There is only one "ambient" transaction when you use a TransactionScope
. Once a TransactionScope
is disposed or gets collected without Complete
being executed, the whole ambient transaction gets rolled back; that's it, game over.
事实上,SQL Server 根本不支持真正的嵌套事务,尽管 有可能(尽管有些不直观)通过适当使用 SAVE TRAN
语句.如果您需要此特定行为,则将此逻辑重新实现为存储过程(或其中几个)可能是您的最佳选择.
In fact, SQL Server doesn't support true nested transactions at all, although it is possible (though somewhat unintuitive) to achieve the same end result with appropriate use of SAVE TRAN
statements. Re-implementing this logic as a Stored Procedure (or several of them) might be your best option if you require this particular behaviour.
这篇关于嵌套/子事务范围回滚的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持html5模板网!