21

मैं एक तरह से एक प्रश्न निष्पादित करने के लिए, जबकि एक TransactionScope जीवित है के लिए देख रहा हूँ के लिए TransactionScope पर ध्यान न दें, और उपेक्षा TransactionScope - मूल रूप से, मैं कोई बात नहीं क्या इस विशेष क्वेरी निष्पादित करने के लिए चाहते हैं।विशिष्ट क्वेरी

मैं ईएफ कोड-प्रथम का उपयोग कर रहा हूं, और जिस तरह से एप्लिकेशन डिज़ाइन किया गया है, एक नए डेटा संदर्भ को एक ही कॉल में कई बार खोला जाता है, प्रत्येक में अपने स्वयं के परिवर्तन होते हैं, और उनमें से सभी एक एकल लेनदेनस्कोप के भीतर होते हैं , जिसमें Complete() है, अंत में कोई असफलता मानते हुए कहा जाता है। संदर्भ के अंदर हम SaveChanges अधिरोहित गया है ताकि किसी भी अपवाद base.SaveChanges() पर होता है, तो हम उसे पकड़ने और लेन-देन वापस रोलिंग से पहले डेटाबेस के लिए लॉग इन कर सकते।

चूंकि SaveChanges लेनदेन के अंदर होता है, इसलिए लॉगिंग स्पष्ट रूप से नहीं होती है, क्योंकि यह मूल कॉल के समान लेनदेन से संबंधित है। मैं केवल लॉगिंग कोड के लिए ट्रांज़ेक्शनस्कोप को अनदेखा करने की कोशिश कर रहा हूं।

यहाँ कुछ छीन नीचे कोड है:

// From the context 
public override int SaveChanges() { 
    try { 
     return base.SaveChanges(); 
    } catch (Exception ex) { 

     // Writes to the log table - I want this to run no matter what 
     LogRepo.Log(/*stuff to log from the context*/); 

     throw; 
    } 
} 

// Inside the business logic 
public void DoSomething() { 
    try { 
     using (var scope = new TransactionScope()) { 

      using (var context = new FooContext()) { 
       // Do something 
       context.SaveChanges(); 
      } 
      using (var context = new FooContext()) { 
       // Do something else 
       context.SaveChanges(); 
      } 

      scope.Complete(); 
     } 
    } catch (Exception ex) { 
     // scope.Complete is never called, so the transaction is rolled back 
    } 
} 

मैं प्रवेश के लिए एफई के बजाय नियमित ADO.NET उपयोग करने की कोशिश, लेकिन अभी भी एक ही परिणाम - इसे वापस भी लुढ़का हो जाता है।

मुझे SaveChanges के अंदर होने वाली त्रुटि प्रबंधन की आवश्यकता है, क्योंकि जो मैं लॉगिंग कर रहा हूं वह उन संस्थाओं की स्थिति है जो सहेजे जा रहे हैं - इसलिए मैं कहीं और आसानी से लॉगिंग नहीं कर सकता। मैं जबकि SaveChanges catch अंदर संदेश बना सकते हैं, और यह फेंक और DoSomething catch यह लोग इन करते हैं, लेकिन वहाँ DoSomething तरीकों के दर्जनों रहे हैं, और मैं बहुत बल्कि सिर्फ एक ही स्थान पर इस समस्या से निपटने चाहते हैं।

उत्तर

29

आप को दबाने विकल्प सक्षम के साथ एक और लेन-देन दायरे के अंदर अपनी लॉग कॉल लपेट तो लेन-देन गुंजाइश उपयोग नहीं किया जाएगा।

public override int SaveChanges() { 
try { 
    return base.SaveChanges(); 
} catch (Exception ex) { 

    string message = /*stuff to log from the context*/; 
    using (var scope = new TransactionScope(TransactionScopeOption.Suppress)) 
    { 
     LogRepo.Log(msg); 

    } 

    throw; 
} 

}

+0

बिल्कुल सही! वास्तव में जो मैं खोज रहा था। परीक्षण किया गया और यह नियमित एडीओ.NET और इकाई फ्रेमवर्क दोनों में काम करता है धन्यवाद। –

+0

बस इसे कार्यान्वित किया गया और अब मुझे यह त्रुटि मिलती है: वितरित लेनदेन प्रबंधक (एमएसडीटीसी) के लिए नेटवर्क एक्सेस अक्षम कर दिया गया है। कृपया घटक सेवा प्रशासनिक टूल का उपयोग कर एमएसडीटीसी के लिए सुरक्षा कॉन्फ़िगरेशन में नेटवर्क एक्सेस के लिए डीटीसी सक्षम करें। मैंने इसे खोलना पढ़ा कई लेन-देन इस त्रुटि का कारण बन सकते हैं? –

+0

इसने मुझे बहुत सी सिरदर्द बचाया! मैं एक लेनदेन के अंदर एमएसएमक्यू संदेशों को संसाधित कर रहा हूं, लेकिन थोड़ा अतिरिक्त डेटा के लिए एसक्यूएल एज़ूर तक पहुंचने की जरूरत है और वे डीटीसी का समर्थन नहीं करते हैं। इसका उपयोग करना मेरे लेन-देन को अभी भी काम करने में सक्षम बनाया गया है, जबकि एज़ूर फ़ंक्शन भी दे रहा है। – RubyHaus

1

बस मेरा प्रारंभिक विचार, लेकिन आपको अपने लॉगरेपो को अपने डेटाकॉन्टेक्स्ट (डीसी 2) पर रखना होगा ताकि आस-पास के लेनदेनस्कोप (डीसी 1 के साथ) इसे वापस नहीं कर पाएंगे।

मूल रूप से, आप अपने प्रवेश संयमी और परमाणु बनाने की जरूरत है।

EDIT इसे और अधिक देखने में, मुझे लगता है कि अगर आप SaveChanges से अपने लॉगिंग को DoSomething() पर कैच() में ले जाते हैं, तो आपका लॉगिंग काम करेगा। लेकिन, आपके लॉगिंग को अभी भी आत्मनिर्भर और परमाणु होना चाहिए।

+0

TransactionScope हर डेटा संदर्भ इसके अंदर है कि चारों ओर अपने आप में लपेटता - LogRepo अपने खुद के ब्रांड नए संदर्भ पैदा करता है, लेकिन यह अभी भी TransactionScope द्वारा उठाया है। –

+0

अपने संपादित के लिए - मैं उल्लेख किया है कि - मैं कम से कम अंदर से त्रुटि संदेश के निर्माण के लिए 'SaveChanges' क्योंकि मैं खुले डेटा संदर्भ के लिए उपयोग की जरूरत है, लेकिन फिर भी अगर मैं वहाँ से संदेश का निर्माण है और कॉलर को फेंक की जरूरत है, मैं कॉलर में कई दर्जन बार लॉगिंग निष्पादित करना है, और मैं इसे एक ही स्थान पर रखने की कोशिश कर रहा हूं। –

+1

हाँ, यह स्पष्ट है कि आपका कार्यान्वयन डिज़ाइन के रूप में काम नहीं करेगा।दूसरा विकल्प आपके लॉगरेपो को लेना होगा और ऐप स्टार्टअप पर बनाया गया एक सिंगलटन बनाना होगा, जिसमें सभी लेनदेन स्कॉप्स के बाहर बनाए गए अपने स्वयं के डीबीसीएन्टेक्स्ट होंगे। सबसे साफ डिजाइन नहीं है, लेकिन यह आपको इस लेनदेनस्कोप व्यवसाय के आसपास ले जाएगा। मुझे अभी तक एक ट्रांज़ेक्शनस्कोप से संदर्भ को "अनइंस्टलिस्ट" करने का कोई तरीका नहीं मिला है ... –

1

मैं एक समाधान है कि मैं के साथ वास्तव में खुश नहीं हूँ पाया है, लेकिन काम करने के लिए लगता है। लेनदेनस्कोप स्पष्ट रूप से केवल वर्तमान धागे को प्रभावित करता है, इसलिए एक नए धागे का उपयोग करके लॉगिंग ठीक काम करता प्रतीत होता है।

public override int SaveChanges() { 
    try { 
     return base.SaveChanges(); 
    } catch (Exception ex) { 

     string message = /*stuff to log from the context*/; 
     new Thread(msg => {  

      LogRepo.Log(msg); 

     }).Start(message); 

     throw; 
    } 
} 
+1

यह निश्चित रूप से इसके लिए एक "icky" भावना है, लेकिन अगर यह काम करता है, तो यह काम करता है। मेरे पास सिंगलटन सुझाव की तरह था। मुझे यह पसंद नहीं है, लेकिन यह निश्चित रूप से काम करेगा। –

+0

@ जोकिन्सचेन +1 "icky" के लिए +1 :) –

+0

यह ठीक है जब मैं डीबग करता हूं। लेकिन रिलीज मोड में या रन में यह काम नहीं कर रहा है :( – mostafa8026

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