2009-10-26 11 views
6

वेब एप्लिकेशन के भीतर ऑटोफैक का उपयोग करके एनएचबीरनेट लेनदेन के प्रबंधन के लिए सबसे अच्छा तरीका क्या है?एएसपी.नेट (एमवीसी) के भीतर ऑटोफैक के साथ एनएचबर्ननेट: आईट्रांसक्शन

सत्र के लिए मेरे दृष्टिकोण

builder.Register(c => c.Resolve<ISessionFactory>().OpenSession()) 
     .ContainerScoped(); 

ITransaction के लिए है, मैं Google Code पर found an example है, लेकिन यह तय करते समय रोलबैक के लिए कि क्या HttpContext.Current.Error पर निर्भर करता है।

वहाँ एक बेहतर समाधान है? और एनएचबीर्नेट लेनदेन का क्या दायरा होना चाहिए?

उत्तर

4

मैं इस थोड़ी देर पहले पोस्ट की गई:

http://groups.google.com/group/autofac/browse_thread/thread/f10badba5fe0d546/e64f2e757df94e61?lnk=gst&q=transaction#e64f2e757df94e61

संशोधित, ताकि इंटरसेप्टर प्रवेश करने की क्षमता है और [लेन-देन] विशेषता कर सकते हैं है एक वर्ग पर भी इस्तेमाल किया जा सकता है।

[global::System.AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] 
public class TransactionAttribute : Attribute 
{ 
} 


public class ServicesInterceptor : Castle.Core.Interceptor.IInterceptor 
{ 
    private readonly ISession db; 
    private ITransaction transaction = null; 

    public ServicesInterceptor(ISession db) 
    { 
     this.db = db; 
    } 

    public void Intercept(IInvocation invocation) 
    { 
     ILog log = LogManager.GetLogger(string.Format("{0}.{1}", invocation.Method.DeclaringType.FullName, invocation.Method.Name)); 

     bool isTransactional = IsTransactional(invocation.Method); 
     bool iAmTheFirst = false; 

     if (transaction == null && isTransactional) 
     { 
      transaction = db.BeginTransaction(); 
      iAmTheFirst = true; 
     } 

     try 
     { 
      invocation.Proceed(); 

      if (iAmTheFirst) 
      { 
       iAmTheFirst = false; 

       transaction.Commit(); 
       transaction = null; 
      } 
     } 
     catch (Exception ex) 
     { 
      if (iAmTheFirst) 
      { 
       iAmTheFirst = false; 

       transaction.Rollback(); 
       db.Clear(); 
       transaction = null; 
      } 

      log.Error(ex); 
      throw ex; 
     } 
    } 

    private bool IsTransactional(MethodInfo mi) 
    { 
     var atrClass = mi.DeclaringType.GetCustomAttributes(false); 

     foreach (var a in atrClass) 
      if (a is TransactionAttribute) 
       return true; 

     var atrMethod = mi.GetCustomAttributes(false); 

     foreach (var a in atrMethod) 
      if (a is TransactionAttribute) 
       return true; 

     return false; 
    } 
} 
+1

मुझे समाधान पसंद है। हालांकि, एक और सवाल यह है कि मैं किस तरीकों को लागू कर सकता हूं [लेनदेन]? इस http://nhprof.com/Learn/Alert?name=DoNotUseImplicitTransactions के मुताबिक ऐसा लगता है कि मेरे पास सत्र होने पर हमेशा लेनदेन होना चाहिए, हालांकि इस समाधान के लिए मुझे सत्र में हर जगह [लेनदेन] मैन्युअल रूप से जोड़ने की आवश्यकता होती है। –

+0

संशोधित संस्करण की जांच करें। आपको शायद पता चलेगा कि इसे वहां से कैसे संशोधित किया जाए। आप [लेनदेन] विशेषता को पूरी तरह से छोड़ सकते हैं और हमेशा लेनदेन शुरू कर सकते हैं। यह तुम्हारी पसंद है। मुझे विशेषता की आवश्यकता थी, क्योंकि कभी-कभी मुझे अलग-अलग लेनदेन में 2 चीजें करने की ज़रूरत होती थी। मैंने इसे ऐसा किया: // कोई लेनदेन विशेषता सार्वजनिक आभासी शून्य कॉल यह() { ट्रांस 1(); // ट्रांस 2(); // करता } [लेन-देन] सार्वजनिक आभासी शून्य Trans1() {} [लेन-देन] सार्वजनिक आभासी शून्य Trans2() {} – dmonlord

+0

आप दो लेनदेन के लिए उपयोग के मामले समझा सकते हैं? यह महत्वपूर्ण है क्योंकि अगर मुझे एक समान उपयोग केस भी मिल सकता है, तो मैं समस्या को अलग-अलग देखूंगा। –

-1

.. मैं आमतौर पर लेन-देन अपने आप का प्रबंधन

public ActionResult Edit(Question q){ 
try { 
using (var t = repo.BeginTransaction()){ 
    repo.Save(q); 
    t.Commit(); 
    return View(); 
} 
catch (Exception e){ 
    ... 
} 
} 
+1

यह सबसे आसान समाधान है, लेकिन यह थोड़ा कठिन है और पूरी विधि में इंडेंट जोड़ता है। –

+0

सुनिश्चित करें, 2 लाइनें और एक इंडेंट, लेकिन कुछ दिन आपको एहसास है कि आपको उसी अनुरोध में दो लेनदेन करना होगा या ऐसा कुछ .. –

+1

अधिकांश लोग ctrl + c/ctrl + v को कई बार दबा नहीं करना पसंद करते हैं – Paco

4

जब मैं autofac का उपयोग मैं एक ही कंटेनर scoped विधि का उपयोग करें, लेकिन इसके बजाय मेरी भंडार/डीएओ वस्तुओं के लिए एक ही सत्र में उत्तीर्ण होने की मैं एक UnitOfWork कंटेनर है कि scoped गुजरती हैं। काम की इकाई इस निर्माता में है।

private readonly ISession _session; 
    private ITransaction _transaction; 

    public UnitOfWork(ISession session) 
    { 
     _session = session; 
     _transaction = session.BeginTransaction(); 
    } 

और निपटाने है:

public void Dispose() 
    { 
     try 
     { 
      if (_transaction != null && 
          !_transaction.WasCommitted && 
          !_transaction.WasRolledBack) 
       _transaction.Commit(); 
      _transaction = null; 
     } 
     catch (Exception) 
     { 
      Rollback(); 
      throw; 
     } 

    } 

मैं कर रहा हूँ (ab) इस का प्रबंधन करने के क्रम में autofac में नियतात्मक निपटान सामान का उपयोग कर, और अच्छी तरह से मैं इन सबसे छुटकारा पाना पसंद है।

दूसरी बात यह है कि मैं मूल रूप से केवल एएसपीनेट पर्यावरण को लक्षित कर रहा हूं और एक सचेत निर्णय लेता हूं कि एक लेनदेन वेब अनुरोध से जुड़ा हुआ है। तो एक वेब अनुरोध पैटर्न प्रति लेनदेन।

इस कारण से मैं यह त्रुटि एक IHttpModule में कोड से निपटने कर सकते हैं:

void context_Error(object sender, System.EventArgs e) 
    { 
     _containerProvider.RequestContainer.Resolve<IUnitOfWork>().Rollback(); 
    } 

मैं NHibernate.Burrow पर एक नज़र भी बारीकी से नहीं लिया है, लेकिन मुझे यकीन है कि वहाँ कुछ वहाँ सबसे करता है हूँ इस का।

+0

आपका विचार ऑटोफैक के समान ही है, और मुझे यह बहुत पसंद है। दुर्भाग्य से, मैं दो उत्तरों को स्वीकार नहीं कर सकता, इसलिए मैं सबसे पहले वह चुनूंगा (डोनलोर्ड की बहुत कम प्रतिष्ठा है)। –

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