2012-01-05 7 views
5

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

हम मुख्य रूप से डेटाबेस से कनेक्ट करने के लिए NHibernate का उपयोग कर रहे हैं। एक आवेदन एक डब्ल्यूसीएफ सेवा है जिसे आने वाले डेटा को नेस्टेड टेबल में डालने की आवश्यकता होती है जो वास्तव में व्यापक हैं (स्तंभों के दर्जनों)। जाहिर है, प्रदर्शन एक मुद्दा है, इसलिए मैं एनएचबीर्नेट लेनदेन के साथ जितना संभव हो उतना आर्थिक होना चाहता हूं। साथ ही, समेकन एक मुद्दा प्रतीत होता है। उत्पादन में, हम कुछ ज़ोंबी लेनदेन त्रुटियों (deadlocks) प्राप्त करने के लिए शुरू कर रहे थे।

मैं इन दो मुद्दों से निपटने के लिए संतुलित संतुलन कर रहा हूं लेकिन वास्तव में समवर्ती समस्याओं को समाप्त नहीं किया है।

सेवा व्यवहार इतना की तरह एक बार में एक अनुरोध को पूरा करने, सेट है:

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode=ConcurrencyMode.Single] 
public class LegacyGateService : ILegacyGateService 

इससे पहले, कुछ "प्रेरणा" के बाद (पढ़ें: कॉपी/पेस्ट) इंटरनेट से, मैं एक जोड़ने समाप्त हो गया क्रमशः सहायक डेटाबेस और विरासत डेटाबेस के लिए XxxNHibernateUtil जैसे कुछ वर्गों को सेट किया गया। ये कक्षाएं एनएचबीर्नेट सत्रों को नियंत्रित करती हैं और सत्रों को पूर्व-प्रारंभिक सत्र कारखानों से उत्पन्न या पुन: उपयोग करती हैं।

सहायक डेटाबेस के लिए यह इस तरह दिखता है:

public static class LegacyGateNHibernateUtil 
{ 
    private static readonly ISessionFactory sessionFactory = BuildSessionFactory(); 

    private static ISessionFactory BuildSessionFactory() 
    { 
     try 
     { 
      Configuration Cfg = new Configuration(); 
      Cfg.Configure(); 
      Cfg.AddAssembly("LegacyGate.Persistence"); 
      return Cfg.BuildSessionFactory(); 
     } 
     catch (Exception ex) 
     { 
      throw ex; 
     } 
    } 

    public static ISessionFactory GetSessionFactory() 
    { 
     return sessionFactory; 
    } 

    public static ISession GetCurrentSession() 
    { 
     if (!CurrentSessionContext.HasBind(GetSessionFactory())) 
      CurrentSessionContext.Bind(GetSessionFactory().OpenSession()); 

     return GetSessionFactory().GetCurrentSession(); 
    } 

    public static void DisposeCurrentSession() 
    { 
     ISession currentSession = CurrentSessionContext.Unbind(GetSessionFactory()); 

     if (currentSession != null) 
     { 
      if (currentSession.IsOpen) 
       currentSession.Close(); 
      currentSession.Dispose(); 
     } 
    } 
} 

जब भी कोई सत्र एक सौदे के लिए आवश्यक है, वर्तमान सत्र ऊपर देखा जाता है और सेवा अनुरोध कॉल की अवधि के लिए फिर से इस्तेमाल किया। या कम से कम: ऐसा ही हो रहा है।

संपादित करें: सत्र संदर्भ पाठ्यक्रम तो जैसे hibernate.cfg.xml में सेट की है:

<property name="current_session_context_class">call</property> 

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

डब्ल्यूसीएफस्टॉर्म का उपयोग करके परीक्षण, यह एक समय में एक अनुरोध भेजते समय ठीक काम करता प्रतीत होता है, लेकिन जैसे ही मैं एक लोड टेस्ट शुरू करता हूं, यहां तक ​​कि केवल एक एजेंट और लंबे अंतराल के साथ, मुझे विभिन्न प्रकार के अपवादों का भरपूर लाभ मिलता है एक दूसरे के साथ मिलकर एक साथ अनुरोध और लेनदेन की ओर इशारा करते हुए। मैंने अलगाव लेवेल को ट्विक करने का प्रयास किया है, लेकिन अब इसका लाभ उठाएं।

मुझे लगता है कि मुझे सत्रों को अलग-अलग तरीके से उत्पन्न करने और संभालने की आवश्यकता है, ताकि एक ही डेटाबेस में अलग-अलग लेन-देन व्यवस्थित तरीके से संभाले जा सकें और एक दूसरे के साथ हस्तक्षेप न करें। हालांकि, मुझे यह काम करने के तरीके में कुछ अंतर्दृष्टि नहीं है। कोई भी मदद बहुत ही सराहनीय होगी!


संपादित एक सेवा पद्धति के लिए, जब एक से अधिक एजेंट, पहली दर्जन फोन काम ठीक है, और फिर अपवाद की निम्न स्ट्रिंग के साथ परीक्षण प्रदर्शित होने कि केवल सहायक डेटाबेस संबंधित शुरू:

  1. "आईडीटाइडर को एनडाटा रीडर में परिवर्तित करने में कोई समस्या थी"/ "पाठक बंद होने पर मेटाडेटा को कॉल करने का अमान्य प्रयास।"
  2. "संग्रह लोड करने के लिए अवैध रूप से उपयोग"
  3. "एसक्यूएल अपवाद के साथ विफल रही शुरू"/"समय समाप्त समाप्त हो गई है। समय समाप्ति की अवधि आपरेशन के पूरा होने या सर्वर से पहले बीत जवाब नहीं है।"
  4. "क्वेरी निष्पादित नहीं कर सका"/"ExecuteReader को एक खुला और उपलब्ध कनेक्शन की आवश्यकता होती है। कनेक्शन का वर्तमान स्थिति बंद है।"
  5. "संग्रह को प्रारंभ नहीं किया जा सका:"/"टाइमआउट समाप्त हो गया। ऑपरेशन पूरा होने से पहले समय समाप्ति अवधि समाप्त हो गई है या सर्वर प्रतिक्रिया नहीं दे रहा है।"
  6. "लेन-देन नहीं सफलतापूर्वक प्रारंभ"
  7. "लेन-देन भी नहीं वर्तमान कनेक्शन साथ जुड़ा हुआ है या पूरा हो चुका है।"
  8. "संग्रह को प्रारंभ नहीं किया जा सका:"/"पाठक बंद होने पर पढ़ने का अमान्य प्रयास पढ़ें।"

अपवाद 1, कम से कम, इंगित करता है कि एक ही सत्र को कई धागे (संभवतः कॉल) द्वारा एक्सेस किया जाता है। साथ ही अन्य संकेत भी देते हैं कि वर्तमान सत्र अन्य प्रक्रियाओं से बाधित है। लेकिन यह कैसे हो सकता है, जब मैंने कॉल को अलग करने की कोशिश की और उन्हें कतारबद्ध किया?

अन्य सेवा विधि के लिए, ये समस्याएं सहायक डेटाबेस के साथ दिखाई नहीं देती हैं, लेकिन कुछ समय बाद मैं विरासत डेटाबेस में लेनदेन के साथ ZombiedTransaction अपवाद (deadlocks) प्राप्त करना शुरू कर देता हूं। फिर भी ... क्या देता है?

+0

ऐसा लगता है जैसे आप समवर्ती मुद्दों में चल रहे हैं। आप एनएच का किस संस्करण का उपयोग कर रहे हैं? यदि आप 3.2 का उपयोग कर रहे हैं तो मैं आपके सत्र संदर्भ के रूप में "wcf_operation" का उपयोग करने का सुझाव दूंगा।यदि आप 3.2 का उपयोग नहीं कर रहे हैं तो भी आप इसे कर सकते हैं एक आसान तरीका है। –

+2

इसके अलावा 'थ्रो एक्स;' बयान भी एक बड़ा नंबर नहीं है। जब आप ऐसा करते हैं तो आप स्टैक ट्रेस को नष्ट कर रहे हैं। आपको 'फेंक' का उपयोग करना चाहिए; चूंकि आप अपवाद के साथ कुछ भी नहीं कर रहे हैं, वहां भी कोशिश करने की कोशिश नहीं की जानी चाहिए। –

+0

क्षमा करें। मैंने आपकी टिप्पणियों को अनदेखा किया। मैं संस्करण 3.1 का उपयोग कर रहा हूं, लेकिन अगर मैं मदद करता हूं तो मैं स्नैप में अपग्रेड कर सकता हूं! :-) और ठीक है, मैं अपने अपवाद नो-नो को ठीक कर दूंगा और भविष्य के लिए इसे ध्यान में रखूंगा! अब तक Thnx! –

उत्तर

12

आसान जवाब: आप फिर से उपयोग नहीं करते NHibernate सत्र।

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

मूल रूप से, सत्रों तक पहुंच को सिंक्रनाइज़ करने की लागत सही ढंग से उन्हें पुन: प्रारंभ करने से बचने के लिए उन्हें रीसाइक्लिंग करके प्राप्त होने वाले किसी भी लाभ को निश्चित रूप से अस्वीकार कर देगी। आइए यह भी मान लें कि ये लागत SQL के तालाब में एक बूंद है जिसे आप निष्पादित करेंगे।

याद रखें कि NHibernate के सत्र फैक्टरी हैवीवेट वस्तु है। यह थ्रेड-सुरक्षित है, इसलिए आप बॉक्स के बाहर सभी अनुरोधों में एक ही उदाहरण साझा कर सकते हैं और साझा करना चाहिए। एक अलग रूप में के रूप में

public class Service : IService 
{ 
    static Service() 
    { 
     Configuration Cfg = new Configuration(); 
     Cfg.Configure(); 
     Cfg.AddAssembly("LegacyGate.Persistence"); 
     Service.SessionFactory = Cfg.BuildSessionFactory(); 
    } 

    protected static ISessionFactory SessionFactory { get; private set; } 

    public void ServiceMethod(...) 
    { 
     using(var session = Service.SessionFactory.CreateSession()) 
     { 
      // Do database stuff 
      ... 
     } 
    } 
} 

:

आपका कोड इस तरह धारणात्मक दिखना चाहिए आदर्श रूप में, आप होगा निर्भरता-इंजेक्शन सेवा में ISessionFactory

+1

यह भी ध्यान देने योग्य होगा कि एनएचबीर्नेट सत्र का उपयोग इकाई ट्रैकिंग के लिए किया जाता है, जो कि यदि आप एक ही सत्र का उपयोग लंबे समय तक करते हैं तो स्मृति व्यवहार की तरह दिखता है (यानी डेटाबेस में सभी इकाइयां सत्र द्वारा ट्रैक की जा सकती हैं)। – Liedman

+0

हमम ... अच्छा बिंदु! तो मूल रूप से GetCurrentSession-method को केवल एक पंक्ति में बदलें: GetSessionFactory()। OpenSession() वापस लौटें; ? –

+0

लेकिन क्या यह डेडलॉक्स को भी खत्म कर देगा? –

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