2012-03-21 14 views
6

मैं एनएचबीर्नेट दृढ़ता परत के लिए अपना खुद का IUnitOfWork कार्यान्वयन करने के बारे में सोच रहा हूं।क्या आपके पास निबर्ननेट में एक सत्र के अंदर कई लेन-देन हो सकते हैं? और क्या यह एक बुरा विचार है?

ऐसा लगता है कि यह करने के लिए सही तरीके से ISession और ITransaction निर्माता में instantiated, और फिर नाशक में निपटाया या Dispose() विधि के लिए किया जाएगा।

बेशक

, किसी Save() विधि का आह्वान है, तो ISession प्लावित किया जाएगा और ITransaction फिर से पूरा होगा, इसलिए Save() बुला के बाद, वहाँ Save() के लिए एक वैध खुला लेन-देन नहीं होगा ... जब तक कि मैंने इसके लिए हामी पहला लेनदेन और तुरंत एक और नया लेनदेन खोला। लेकिन क्या यह एक अच्छा विचार है?

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

क्या मैं यूनिटऑफवर्क प्रति सत्र कई लेनदेन के लिए सहिष्णु बनाने की कोशिश करके कुछ खो देता/प्राप्त करता हूं? क्या मुझे सिर्फ एक नया लेनदेन करने की बजाय एक खुले लेनदेन की जांच करनी चाहिए और अपवाद फेंकना चाहिए?

+0

वेब या डेस्कटॉप ऐप? – Phill

+0

इसे एक वेब एप्लिकेशन के लिए डिज़ाइन किया जा रहा है। –

उत्तर

11

पहले प्रश्न का उत्तर देने के लिए: हाँ एक सत्र में कई लेनदेन करना संभव है।

क्या एक अच्छा विचार है? निर्भर करता है।

समस्या यह है कि पहले लेनदेन में डेटा बदलना होगा, जबकि यह सुनिश्चित नहीं है कि काम की पूरी इकाई (सत्र) अंत में प्रतिबद्ध हो जाती है। जब आप पाते हैं, तो बाद में लेनदेन में एक StaleObjectException कहें, आपके पास पहले से ही कुछ डेटा किया गया है। ध्यान दें कि इस प्रकार का अपवाद आपके सत्र को अनुपयोगी बनाता है और आपको वैसे भी इसे नष्ट करना पड़ा। फिर शुरू करना और फिर से प्रयास करना मुश्किल है।

मैं कहूंगा, यह इन परिस्थितियों में अच्छी तरह से काम करता है:

  • यह एक यूआई आवेदन
  • परिवर्तन केवल अंतिम लेन-देन में प्लावित कर रहे हैं है।

यूआई आवेदन

त्रुटियाँ सहभागी उपयोगकर्ता द्वारा नियंत्रित किया जाता है।इसका अर्थ यह है कि उपयोगकर्ता देख सकता है कि वास्तव में त्रुटि के मामले में क्या संग्रहीत किया जाता है और उसके द्वारा किए गए परिवर्तनों को दोहराता है।

परिवर्तन केवल अंतिम लेनदेन

में प्लावित कर रहे हैं सत्र के रूप में राष्ट्रीय राजमार्ग द्वारा कार्यान्वित केवल अंत में परिवर्तन या "जब आवश्यक" flushes। इसलिए सत्र पूरा होने तक स्मृति में परिवर्तन रखना संभव होगा। समस्या यह है कि एनएच को हर प्रश्न से पहले सत्र को फ्लश करने की जरूरत है, जिसे नियंत्रित करना मुश्किल है। इसे बंद कर दिया जा सकता है, जो साइड इफेक्ट्स की ओर जाता है। सरल लेनदेन लिखते समय, आप इसे नियंत्रण में रख सकते हैं। एक जटिल प्रणाली में यह सुनिश्चित करना लगभग असंभव है कि कुछ भी गलत नहीं हो रहा है।

सरल तरीका (टीएम)

मैं एक काफी बड़ी क्लाइंट-सर्वर सिस्टम के हठ परत लिखा था। ऐसी प्रणाली में, आपके पास उपयोगकर्ता को त्रुटियों को सीधे संभाल नहीं है। आपको सिस्टम में त्रुटियों को संभालने और एक स्थिर स्थिति में ग्राहक को नियंत्रण वापस करने की आवश्यकता है।

मैंने इसे स्थिर और "बेवकूफ सबूत" बनाने के लिए पूरे लेनदेन से निपटने को पूर्ण न्यूनतम तक सरल बना दिया। मेरे पास हमेशा एक सत्र और एक लेनदेन एक साथ बनाया गया है और यह या तो प्रतिबद्ध हो जाता है या नहीं।

+0

मेरी समझ यह है कि 'ITransaction.Commit()' आमंत्रण सत्र को फ्लश करेगा। उसी सत्र का उपयोग करके एक नया 'आईट्रांसक्शन' स्थापित करना, और 'Commit() 'के तुरंत बाद, कौन सी परिस्थितियां' StaleObjectException' उत्पन्न करेंगी? –

+0

लेनदेन रिलीज लॉक जारी करना। इससे StaleObjectExceptions प्राप्त करने की अधिक संभावना होती है। लेकिन आप उन्हें वैसे भी प्राप्त कर सकते हैं, क्योंकि जब आप इसे स्मृति में बदल रहे हैं तो डेटा डीबी में बदल सकता है। एनएच की आशावादी लॉकिंग कम से कम इन संघर्षों का पता लगाना संभव बनाता है। विस्तृत उत्तर के लिए –

+1

धन्यवाद। –

2

काम की इकाई के साथ निहिरनेट नेस्टेड लेनदेन को लागू करने के लिए कई विकल्प उपलब्ध हैं।

यहां मैं काम की इकाई के लिए कमांड पैटर्न का उपयोग कर रहा हूं।

public interface IAction 
{  
    void Execute(); 
} 

public abstract class Action<T> : IAction, IDisposable where T : Action<T> 
{ 
    public void Execute() 
    { 
     try 
     { 
      //Start unit of work by your unit of work pattern or 
      transaction.Begin(); 
      OnExecute(); 
      //End Unit of work 
      transaction.Commit(); 
     } 
     catch (Exception e) 
     { 
      transaction.Rollback(); 
      throw e; 
     } 
    } 

    protected abstract void OnExecute(); 

    public void Dispose() 
    { 

    } 
} 

public class MyBusinessLogic : Action<MyBusinessLogic> 
{ 
    protected override void OnExecute() 
    { 
     //Implementation 
    } 
} 

public class MyAnotherBusinessLogic : Action<MyAnotherBusinessLogic> 
{ 
    protected override void OnExecute() 
    { 
     //Nested transaction 
     MyBusinessLogic logic = new MyBusinessLogic(); 
     logic.Execute(); 
    } 
} 
+0

बस कुछ चीजों को इंगित करने के लिए: 1) पहले से ही एक सिस्टम है। एक्शन ताकि यह नाम-विवेकपूर्ण भ्रमित हो जाए। 2) आपकी एक्शन कक्षा परिभाषित नहीं करती है कि लेनदेन कहां से आता है। 3) यह अभी भी वही त्रुटियों का कारण बन जाएगा क्योंकि नेस्टेड लेनदेन पहले ही एनएचबीर्नेट में होता है (आंतरिक लेनदेन करने से बाहरी लेनदेन एक ऑब्जेक्ट डिस्प्ले अपवाद को फेंक देगा)। – rossisdead

0

मुझे लगता है कि काम की प्रति इकाई एक लेनदेन के साथ समाधान बहुत ही सीमित है। कुछ वातावरण में प्रति सत्र में कई लेन-देन करने की क्षमता की आवश्यकता हो सकती है। मैं स्वयं लेनदेन को स्पष्ट रूप से प्रबंधित करता हूं और यह एक लचीला समाधान प्रतीत होता है।

public interface IUnitOfWork: IDisposable 
{ 
    IGenericTransaction BeginTransaction(); 
} 

public interface IGenericTransaction: IDisposable 
{ 
    void Commit(); 

    void Rollback(); 
} 

public class NhUnitOfWork: IUnitOfWork 
{ 
    private readonly ISession _session; 

    public ISession Session 
    { 
     get { return _session; } 
    } 

    public NhUnitOfWork(ISession session) 
    { 
     _session = session; 
    } 

    public IGenericTransaction BeginTransaction() 
    { 
     return new NhTransaction(_session.BeginTransaction()); 
    } 

    public void Dispose() 
    { 
     _session.Dispose(); 
    } 
} 

public class NhTransaction: IGenericTransaction 
{ 
    private readonly ITransaction _transaction; 

    public NhTransaction(ITransaction transaction) 
    { 
     _transaction = transaction; 
    } 

    public void Commit() 
    { 
     _transaction.Commit(); 
    } 

    public void Rollback() 
    { 
     _transaction.Rollback(); 
    } 

    public void Dispose() 
    { 
     _transaction.Dispose(); 
    } 
} 

उपयोग इस तरह दिखता है। यह किसी भी पैटर्न में आसानी से शामिल किया जाता है।

public void Do(IUnitOfWork uow) 
{ 
    using (var tx = uow.BeginTransaction()) { 
    // DAL calls 
    tx.Commit(); 
    } 
} 
+0

यह वही है जो हम भी करते हैं लेकिन यह इस मामले में काम नहीं करता है: मुझे लगता है कि एक टिप्पणी में कोड संपादन नहीं कर सकता ... लेकिन यदि आपके अंदर एक और लेनदेन है तो यह काम नहीं करता है। लेकिन यह चाहिए। अच्छे कारणों से डेटाबेस में नेस्टेड लेनदेन लागू किए जाते हैं। – user2415376

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

  • कोई संबंधित समस्या नहीं^_^