C# 如何知道代码是否在 TransactionScope 内?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/980337/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to know if the code is inside TransactionScope?
提问by nightcoder
What is the best way to know if the code block is inside TransactionScope?
Is Transaction.Current a realiable way to do it or there are any subtleties?
Is it possible to access internal ContextData.CurrentData.CurrentScope (in System.Transactions) with reflection? If yes, how?
知道代码块是否在 TransactionScope 内的最佳方法是什么?
Transaction.Current 是一种可行的方法还是有任何微妙之处?
是否可以通过反射访问内部 ContextData.CurrentData.CurrentScope(在 System.Transactions 中)?如果是,如何?
采纳答案by nightcoder
Here is more reliable way (as I said, Transaction.Current can be set manually and it doesn't always mean we are really in TransactionScope). It's also possible to get this information with reflection, but emiting IL works 100 times faster than reflection.
这是更可靠的方法(正如我所说,Transaction.Current 可以手动设置,并不总是意味着我们真的在 TransactionScope 中)。也可以通过反射获取这些信息,但发出 IL 的工作速度比反射快 100 倍。
private Func<TransactionScope> _getCurrentScopeDelegate;
bool IsInsideTransactionScope
{
get
{
if (_getCurrentScopeDelegate == null)
{
_getCurrentScopeDelegate = CreateGetCurrentScopeDelegate();
}
TransactionScope ts = _getCurrentScopeDelegate();
return ts != null;
}
}
private Func<TransactionScope> CreateGetCurrentScopeDelegate()
{
DynamicMethod getCurrentScopeDM = new DynamicMethod(
"GetCurrentScope",
typeof(TransactionScope),
null,
this.GetType(),
true);
Type t = typeof(Transaction).Assembly.GetType("System.Transactions.ContextData");
MethodInfo getCurrentContextDataMI = t.GetProperty(
"CurrentData",
BindingFlags.NonPublic | BindingFlags.Static)
.GetGetMethod(true);
FieldInfo currentScopeFI = t.GetField("CurrentScope", BindingFlags.NonPublic | BindingFlags.Instance);
ILGenerator gen = getCurrentScopeDM.GetILGenerator();
gen.Emit(OpCodes.Call, getCurrentContextDataMI);
gen.Emit(OpCodes.Ldfld, currentScopeFI);
gen.Emit(OpCodes.Ret);
return (Func<TransactionScope>)getCurrentScopeDM.CreateDelegate(typeof(Func<TransactionScope>));
}
[Test]
public void IsInsideTransactionScopeTest()
{
Assert.IsFalse(IsInsideTransactionScope);
using (new TransactionScope())
{
Assert.IsTrue(IsInsideTransactionScope);
}
Assert.IsFalse(IsInsideTransactionScope);
}
回答by Marc Gravell
Transaction.Current
should be reliable; I've just checked, at this works fine with suppressed transactions, too:
Transaction.Current
应该是可靠的;我刚刚检查过,这也适用于抑制交易:
Console.WriteLine(Transaction.Current != null); // false
using (TransactionScope tran = new TransactionScope())
{
Console.WriteLine(Transaction.Current != null); // true
using (TransactionScope tran2 = new TransactionScope(
TransactionScopeOption.Suppress))
{
Console.WriteLine(Transaction.Current != null); // false
}
Console.WriteLine(Transaction.Current != null); // true
}
Console.WriteLine(Transaction.Current != null); // false