2009-06-11 5 views
25

यह जानने का सबसे अच्छा तरीका क्या है कि कोड ब्लॉक ट्रांज़ेक्शनस्कोप के अंदर है या नहीं?
लेनदेन है। इसे करने के लिए एक वास्तविक तरीका है या कोई subtleties हैं?
क्या प्रतिबिंब के साथ आंतरिक ContextData.CurrentData.CurrentScope (System.Transactions में) तक पहुंच बनाना संभव है? यदि हां, तो कैसे?कैसे पता चलेगा कि कोड ट्रांज़ेक्शनस्कोप के अंदर है या नहीं?

उत्तर

4

यहाँ और अधिक विश्वसनीय तरीका है (जैसा कि मैंने कहा, Transaction.Current मैन्युअल रूप से सेट किया जा सकता है और यह हमेशा मतलब यह नहीं है कि हम वास्तव में कर रहे हैं लेनदेनस्कोप में)। प्रतिबिंब के साथ यह जानकारी प्राप्त करना भी संभव है, लेकिन आईएल उत्सर्जित प्रतिबिंब से 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); 
} 
+1

मुझे आश्चर्य है कि आपने चार वर्षों तक उत्पादन में इस कोड का उपयोग करने के बाद "विश्वसनीय" की अपनी परिभाषा बदल दी है। –

+0

यदि लेनदेन। वर्तमान विश्वसनीय नहीं है, तो क्यों नहीं। नेट देव ने इसे पढ़ा? क्या आपने इसके कार्यान्वयन को देखा है? –

+3

यह .NET 4.5 "CurrentData" में दिखाई देता है जिसका नाम बदलकर "TLSCurrentData" कर दिया गया है –

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

मेरा मतलब है कि लेनदेन। वर्तमान संपत्ति को तब भी सेट किया जा सकता है जब हम लेनदेनस्कोप में न हों। – nightcoder

+1

यदि ट्रांज़ेक्शनस्कोप पूरा हो गया है, लेकिन अभी भी निपटान नहीं किया गया है, Syste.Transactions.Transaction.Curre एक अपवाद फेंकता है –

संबंधित मुद्दे