带线程的嵌套 TransactionScope,带或不带外部 transactionScope
我对数据库层进行原子写入(插入、更新),将以多种方式调用: 有时它们会被原子地调用,在这种情况下,代码必须创建一个新的环境事务。
在其他情况下,可以从业务层中启动事务范围的父业务流程调用它们,其中原子操作是必须全部位于同一事务中的许多此类数据库操作之一。在这些情况下,操作必须加入由最外层事务范围 using 语句创建的环境事务中。 最后,在某些情况下,最外层业务流程或最外层事务范围 using 语句正在创建环境事务并运行多个线程来完成其工作,并且每个线程都执行事务中必须进行的数据库工作。在这些情况下,我需要使用 DependentTransaction
模式。 (在其他场景中,我使用单元测试中的这种模式,我希望整个过程不会在数据库中留下永久足迹)。
那么,我如何(或者应该)对内部 using
语句进行编码(在嵌套的所有级别),以确保它在从外部事务调用时能够正常运行dependentTransaction,当它被自己调用并且没有环境事务时?
private static readonly TransactionOptions txOptRC =
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted };
// need this when called by itself or from non-threaded outer Tx ...
using (var scop = new TransactionScope(TransactionScopeOption.Required, txOptRC))
{
// Transactional work here
scop.Complete();
}
// need this when called from a multi-threaded or ThreadPooled outer Tx
using (var scop = new TransactionScope(dependentTransaction))
{
// Transactional work here
scop.Complete();
}
我正在考虑的一种方法是:
public void MyMethod( , , , , , DependentTransaction depTx = null)
{
using (var scop = depTx != null?
new TransactionScope(depTx):
TransactionScope(TransactionScopeOption.Required, txOptRC))
{
// Transactional Work here
scop.Complete();
}
// other stuff
}
这会导致任何问题吗?
另外,(第二个问题)据我了解,这种克隆的依赖事务模式仅在您在多个线程上调用从属(较低嵌套)事务工作的嵌套点或异步调用(以某种方式)时才需要。不确定外部 transactionScope 代码无法在内部嵌套事务投票之前完成并退出 using 块的右大括号...
那么这是否意味着如果 transactionScopes 的内部嵌套(其中所有内容都是同步的并且在单个事务上)线程),不需要处理克隆的依赖事务吗?这种性质的内部嵌套 transactionScopes 可以简单地使用标准构造吗?如果这是真的,我只需在代码创建多个的地方使用上述条件语法?异步线程或调用从属方法...
I have atomic writes (inserts, updates) to the database layer which will be called in a variety of ways:
Sometimes they will be called atomically, in which case the code must create a new ambient transaction.
In other situations they can be called from a parent business process in the business layer which initiates a transaction scope, where the atomic operation is one of many such database operations that must all be in the same transaction. In these cases the operation must enlist in the ambient transaction created by the outermost transaction scope using statement.
Finally, in some cases the outermost business process or outermost transaction scope using statement is creating an ambient transaction and running multiple threads to accomplish its work, and each thread does dataabse work which must be in the transaction. In these cases I need to use the DependentTransaction
pattern. (Among other scenarios, I use this pattern from unit tests where I want the entire process to leave no permanent footprints in the DB).
So, how can I (or should I) code the inner using
statments, (at all levels of the nesting), to ensure that it will function properly both when it is called from an outer transaction with a dependantTransaction, and when it is called by itself and there is no ambient transaction ??
private static readonly TransactionOptions txOptRC =
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadCommitted };
// need this when called by itself or from non-threaded outer Tx ...
using (var scop = new TransactionScope(TransactionScopeOption.Required, txOptRC))
{
// Transactional work here
scop.Complete();
}
// need this when called from a multi-threaded or ThreadPooled outer Tx
using (var scop = new TransactionScope(dependentTransaction))
{
// Transactional work here
scop.Complete();
}
One approach I am considering is:
public void MyMethod( , , , , , DependentTransaction depTx = null)
{
using (var scop = depTx != null?
new TransactionScope(depTx):
TransactionScope(TransactionScopeOption.Required, txOptRC))
{
// Transactional Work here
scop.Complete();
}
// other stuff
}
would this cause any issues ?
Also, (second question) as I understand it, this cloned dependant transaction pattern is only necessary at the point in the nesting where you are calling subordinate (lower nested) transactional work on multiple threads, or asynchronously, (in a manner that where it is not determinisitc that the outer transactionScope code cannot finish and drop out of the closing brace of the using block before the inner nested transactions have voted...
So does this mean that if inner nestings of transactionScopes (where everything is synchronous and on a single thread), do not need to deal with the cloned dependent transaction? Can inner nested transactionScopes of this nature then simply use the standard construction ? If this is true I would only have to use the above condiitonal syntax at the point where the code creates multiple threads or calls a subordinate method asynhronously...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
一旦将外部事务作为参数,我就会有相同方法的两个重载,而另一个则什么也得不到。
问题主体中的两个块将成为这两个重载,然后我会将您刚刚调用的所有公共代码放入
该类的私有方法中,这样就不会编写两次。
I would have two overloads of same method once gets the outer transaction as parameter and the other one gets nothing.
your two blocks from the question's body would become those two overloads, I would then put all the common code as you have just called it:
into a private method of the class so to do not write it twice.