2009-06-11 41 views
25

知道代碼塊是否在TransactionScope中的最佳方式是什麼?
是Transaction.Current做一個可行的方法或有任何微妙之處?
是否有可能通過反射訪問內部ContextData.CurrentData.CurrentScope(在System.Transactions中)?如果是,如何?如何知道代碼是否在TransactionScope中?

回答

4

這裏是更可靠的方式(正如我所說,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); 
} 
35

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 
+0

我的意思是,即使我們不在TransactionScope中,也可以設置Transaction.Current屬性。 – nightcoder 2009-06-11 10:31:14

+1

如果TransactionScope已完成但尚未處置,Syste.Transactions.Transaction.Curre會引發異常 – 2016-05-18 13:06:51

相關問題