2009-11-19 18 views
5

मैं विरासत संस्थाओं है कि NHibernate के साथ मैप नहीं कर रहे हैं के साथ NHibernate उपयोग करने के लिए कोशिश कर रहा हूँ की इजाजत दी। अवसर पर इसका मतलब है कि मुझे डेटाबेस में एनएचबीरनेट डेटा को मैन्युअल रूप से फ़्लश करने की आवश्यकता है ताकि जब मैं एनएचबर्ननेट-मैप किए गए इकाइयों के साथ विरासत इकाइयों को जोड़ने का प्रयास करता हूं तो मुझे विदेशी कुंजी अपवाद नहीं मिलते हैं।फ्लश NHibernate जबकि अभी भी लेन-देन रोलबैक

एक समस्या तब होती है जब यह एक सौदे कि फिर वापस लुढ़का किए जाने की आवश्यकता के अनुसार होता है। NHibernate से फ़्लश डेटा रोलबैक नहीं है।

क्या मैं इसके बारे में कुछ भी कर सकता हूं?

अद्यतन

फिर भी उत्सुक ऐसा करने के तरीके - मैं पता मुद्दा दिए गए उत्तर में से किसी पर विश्वास नहीं है। मुझे फ्लश() को कॉल करने की आवश्यकता है। सवाल यह है कि, मैं फ्लैश डेटा कैसे चला सकता हूं?

+0

कृपया मुझे बताएं कि डाउनवोट क्यों? वर्तमान उत्तर अच्छे हैं, लेकिन इस मुद्दे को हल न करें - मुझे डेटाबेस में फ्लश करने में सक्षम होना चाहिए ताकि गैर-एनएचबीरनेट प्रबंधित क्वेरी एनएचबीरनेट में अपडेट किए गए डेटा तक पहुंच सकें। अगर मैं फ्लश नहीं कह सकता हूं, तो गैर-एनएचबीरनेट प्रबंधित क्वेरी कैसे डेटा तक पहुंच सकते हैं? कल्पना कीजिए, इसे सरल सिस्टम के साथ स्वयं करें। डेटा। SQL क्लाइंट कॉल - यह काफी सरल होगा: एक लेन-देन में SqlCommand.ExecuteUpdate() कॉल का एक गुच्छा लपेटें और यह सब कुछ है। आप लेनदेन घोंसला कर सकते हैं, उन्हें वापस रोल कर सकते हैं और सबकुछ अपेक्षित व्यवहार करेगा। – cbp

उत्तर

2

NHibernate के साथ लेन-देन का उपयोग करते समय transaction.Commit) का उपयोग (यह) session.flush कॉल (आंतरिक Session.Flush() का उपयोग कर से बचने की कोशिश और बदले।

दौरान अगर कमिट() एक त्रुटि होती है और लेन-देन इस इस तरह संबोधित किया जा सकता वापस लुढ़का किया जाना चाहिए।

public static void CommitChanges() 
{ 
    ITransaction transaction = Session.BeginTransaction(); 

    try 
    { 
     transaction.Commit(); 
    } 
    catch (HibernateException ex) 
    { 
     transaction.Rollback(); 
     //close and dispose session here 
     throw ex; 
    } 
    finally 
    { 
     transaction.Dispose(); 
    } 
} 

अब, एक मैनुअल कॉल फ्लश करने के लिए करता है, तो() या एक प्रतिबद्ध करने के लिए कॉल() के माध्यम से सफलतापूर्वक वहाँ लेनदेन NHibernate प्रक्रियाओं का उपयोग करके वापस रोल करने के लिए एक तरीका नहीं है चला जाता है। खासकर जब transaction.Commit बुला() को आदेश AdoTransaction NHibernate द्वारा बनाई तो निपटान किया जाता है सही होने के बाद कमिट() खत्म तो आप वापस रोल में इसे का उपयोग नहीं कर सकते।

कोड नमूना ऊपर आप त्रुटियों कि ऐसा दौरान प्रतिबद्ध और फिर लेन-देन कि पहले से ही शुरू कर दिया है वापस रोल को पकड़ने के लिए अनुमति देता है।

अब लेनदेन को कॉल करने के बजाय। नमूना में कॉमिट() सत्र को कॉल करें। मेरे परीक्षणों में फ्लश() डेटाबेस में कोई डेटा सहेजा नहीं जाता है क्योंकि लेनदेन कभी नहीं किया जाता है।

मुझे नहीं पता कि आपका कोड कैसा दिखता है, लेकिन यदि आप पैटर्न में कॉल कर रहे हैं, जैसा ऊपर कोड नमूना दिखाता है, तो सत्र के बजाय लेनदेन.com()। फ्लश() इसे आपको एक रास्ता देना चाहिए आप जो चाहते हैं उसे प्राप्त करने के लिए।

+0

आपका कैच (...) सेक्शन कुछ भी कार्यात्मक नहीं जोड़ता है, क्योंकि निपटान() पहले से ही रोलबैक करता है (यदि नहीं किया जाता है)। – tofi9

+0

@taoufik मुझे डर है कि आपकी टिप्पणी अमान्य है। NHibernate इंटरफ़ेस में AdoTransaction ऑब्जेक्ट द्वारा कार्यान्वित किए गए ITRansaction इंटरफ़ेस का निपटान() कमांड केवल प्रबंधित और अप्रबंधित संसाधनों को मुक्त करने के लिए ज़िम्मेदार है। इसके अलावा एनएचबीर्नेट स्रोत कोड में एक त्वरित रूप से तथ्य यह साबित हुआ कि निपटान() ITransaction.RollBack() या अंतर्निहित IDbTransaction ऑब्जेक्ट की रोलबैक() विधि को कॉल नहीं करता है ... इसलिए पकड़ (...) अनुभाग पूरी तरह कार्यात्मक है और उपरोक्त कोड नमूना के लिए आवश्यक है। – tolism7

+0

निम्न पोस्टिंग एक कोड स्निपेट (प्रतिबिंबक से) दिखाती है जो साबित करती है कि निपटान रोलबैक कॉल करता है: http: // stackoverflow।कॉम/प्रश्न/641660/एक-उपयोग-कथन-रोलबैक-ए-डेटाबेस-लेन-देन-अगर-त्रुटि-होता है – tofi9

3

स्वरूपण के लिए मैं खुद को टोलिज्म 7 के उत्तर को अपडेट करने की अनुमति देता हूं।

  1. उपयोग using और transaction.Dispose (के बारे में भूल) - transaction स्वचालित रूप से ब्लॉक का उपयोग के अंत में Dispose 'की घ हो जाएगा।
  2. throw - क्योंकि यह आपके स्टैकट्रेस दूर फेंकने का मतलब पूर्व फेंक नहीं है (देखें this post यह जहां कहा गया है ".नेट फ्रेमवर्क इस बयान निष्पादित करता है जब:। throw ex; यह फेंक देता है वर्तमान समारोह सब से ऊपर ढेर जानकारी")

public void CommitChanges() 
{ 
    using (var transaction = Session.BeginTransaction()) // <-- open scope 
     try 
     { 
      // do something 
      transaction.Commit(); 
     } 
     catch (HibernateException) 
     { 
      transaction.Rollback(); 
      _session.Close(); 
      _session.Dispose(); 

      throw; // <-- this way the stacktrace stays intact! 
     } 
} 

कोड के इस टुकड़े का एक VB.NET versionhere पाया जा सकता है।

4

जाँच करें: Force query execution without flush/commit

मैं एक ही समस्या है लग रहा था, मैं फ्लश और फिर मैं रोलबैक है लेकिन उसमें कुछ डेटा डेटाबेस में कायम रहेगा। हालांकि, मेरे कोड में कुछ हिस्सों थे जो एक प्रतिबद्धता को बुलाएंगे, जिन्हें वापस नहीं किया जा सकता है। स्वीकार्य उत्तर 'कोड स्निपेट पर लेनदेन, फ्लश, रोलबैक और प्रतिबद्धता के लिए उचित उपयोग के रूप में विचार करें और इस पैटर्न को विस्तारित किया जा सकता है ...

कार्य की एक इकाई में (यानी हम एक अनुरोध में विचार करते हैं काम की एक इकाई के रूप वेब अनुप्रयोग और सब कुछ है कि उस अनुरोध में क्या होता है एक एकल लेनदेन जो onEndRequest लिए प्रतिबद्ध है में मौजूद है):

  1. आप _sessionFactory.OpenSession(), _session.BeginTransaction(), _session.CommitTransaction() और _session.CloseSession() केवल एक बार कहते हैं।

  2. आप जितनी बार चाहें _session.Flush() और _session.RollBackTransaction() पर कॉल कर सकते हैं, लेकिन Flush() स्वचालित रूप से Commit पर स्वचालित रूप से कॉल किया जाता है। जब आपको कोई प्रश्न पूछने की आवश्यकता होती है और यह सुनिश्चित किया जाता है कि प्राप्त डेटा खराब नहीं होगा, तो आप फ्लश को कॉल करना चाहेंगे।

  3. ध्यान दें कि एक बार एक प्रतिबद्ध लेनदेन किया जाता है, तो बाद में सभी लेनदेन उस लेनदेन पर नहीं होते हैं। इसके बजाय NHibernate हुड (http://www.nhprof.com/Learn/Alerts/DoNotUseImplicitTransactions) जो बिंदु में आप पहले से ही

  4. तुम सच में कॉल करना होगा तो काम की अपनी यूनिट के बीच में प्रतिबद्ध यह दृढ़ता से सलाह दी जाती है समस्याओं पर नज़र रखने स्थिरता और संभवतः तार्किक अखंडता है के तहत आवश्यक लेन-देन का निर्माण करेगा उस बिंदु पर एक नया लेनदेन बनाने के लिए ताकि आप इसे स्पष्ट रूप से प्रबंधित कर सकें

  5. नेस्टेड लेनदेन को आंशिक रूप से करने की अनुमति देने के लिए और भी बेहतर क्या है; आप "रूट" लेनदेन को रोलबैक कर सकते हैं और सभी परिवर्तन वापस कर दिए जाएंगे। मैंने वास्तव में .NET और SQL सर्वर की इस सुविधा का परीक्षण नहीं किया है, हालांकि डेटाबेस में नेस्टेड लेनदेन स्वयं वांछित होने के लिए बहुत कुछ छोड़ देता है और मुझे नहीं पता कि वास्तव में ADO.NET इस सुविधा को कैसे मापता है।

अंक 1 से 4 को 1.2 से शुरू होने वाले एनएचबर्ननेट के सभी संस्करणों के साथ परीक्षण किया गया है।

+0

आपकी टिप्पणी के लिए धन्यवाद। आपके परीक्षण में आपने देखा था कि एक बार डेटा फ़्लश हो जाने पर लेनदेन को रोलबैक करना संभव नहीं होता है? यही कारण है कि मुझे सिरदर्द पैदा हो रहा है: कभी-कभी आपको लेनदेन के माध्यम से भागने की ज़रूरत होती है, लेकिन आपको बाद में लेनदेन को फिर से चलाने में सक्षम होना चाहिए। यह NHibernate के साथ संभव नहीं प्रतीत होता है। – cbp

+0

अगर उन्हें फ्लश किया गया है तो वे पूरी तरह से रोलबैक योग्य हैं। आपको अपने डीबी ऑपरेशंस को प्रोफाइल करना होगा, शायद कुछ कॉल करने/प्रतिबद्ध करने का कारण बन रहा है। मैं स्पष्ट और निहित फ्लश कर रहा हूं (जब आप उदाहरण के लिए एक एचक्यूएल/मानदंड क्वेरी बनाते हैं) और बिना किसी समस्या के लेनदेन के अंत में रोलबैक (अपवादों या परीक्षण के लिए) कर रहे हैं। – Jaguar

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