एंटिटी फ्रेमवर्क और कनेक्शन पूलिंग


268

मैंने हाल ही में अपने .NET 4.0 एप्लिकेशन में एंटिटी फ्रेमवर्क 4.0 का उपयोग करना शुरू किया है और पूलिंग से संबंधित कुछ चीजों के बारे में उत्सुक हूं।

  1. कनेक्शन पूलिंग जैसा कि मुझे पता है कि MS SQL सर्वर के मामले में ADO.NET डेटा प्रदाता द्वारा प्रबंधित किया जाता है। क्या यह तब लागू होता है जब आप एक नई संस्थाओं के संदर्भ ( ObjectContext) को मापते हैं, यानी पैरामीटरहीन new MyDatabaseModelEntities()?

  2. आवेदन के लिए एक वैश्विक संस्थाओं के संदर्भ (यानी एक स्थिर उदाहरण) या बी) बनाने और एक usingब्लॉक के साथ प्रत्येक दिए गए संचालन / विधि के लिए एक संस्थाओं के संदर्भ को उजागर करने के फायदे और नुकसान क्या हैं ।

  3. किसी भी अन्य सिफारिशों, सर्वोत्तम प्रथाओं, या कुछ परिदृश्यों के लिए सामान्य दृष्टिकोण, जिनके बारे में मुझे पता होना चाहिए?

जवाबों:


369
  1. कनेक्शन पूलिंग को किसी अन्य ADO.NET एप्लिकेशन के रूप में संभाला जाता है। इकाई कनेक्शन अभी भी पारंपरिक कनेक्शन स्ट्रिंग के साथ पारंपरिक डेटाबेस कनेक्शन का उपयोग करता है। मेरा मानना ​​है कि यदि आप इसका उपयोग नहीं करना चाहते हैं तो आप कनेक्शन स्ट्रिंग में कन्वेक्शन पूलिंग को बंद कर सकते हैं। ( SQL सर्वर कनेक्शन पूलिंग (ADO.NET) के बारे में अधिक पढ़ें )
  2. कभी भी वैश्विक संदर्भ का उपयोग न करें। ObjectContext आंतरिक रूप से पहचान मानचित्र और कार्य की इकाई सहित कई पैटर्न लागू करता है। वैश्विक संदर्भ का उपयोग करने का प्रभाव प्रति एप्लिकेशन प्रकार अलग है।
  3. वेब अनुप्रयोगों के लिए प्रति अनुरोध एकल संदर्भ का उपयोग करें। वेब सेवाओं के लिए प्रति कॉल एकल संदर्भ का उपयोग करें। WinForms या WPF आवेदन में प्रति प्रपत्र या प्रस्तुतकर्ता के लिए एकल संदर्भ का उपयोग करें। कुछ विशेष आवश्यकताएं हो सकती हैं जो इस दृष्टिकोण का उपयोग करने की अनुमति नहीं देंगी लेकिन ज्यादातर स्थिति में यह पर्याप्त है।

यदि आप जानना चाहते हैं कि WPF / WinForm एप्लिकेशन के लिए एकल वस्तु संदर्भ का क्या प्रभाव है, तो इस लेख को देखें । यह NHibernate सत्र के बारे में है लेकिन विचार समान है।

संपादित करें:

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

जब तक आप SaveChangesसंदर्भ पर कॉल नहीं करते तब तक इकाई में किए गए किसी भी परिवर्तन को जारी नहीं रखा जाता है। आप कई संस्थाओं में बदलाव कर सकते हैं और उन्हें एक ही बार में स्टोर कर सकते हैं। इसे यूनिट ऑफ वर्क पैटर्न कहा जाता है । आप चुनिंदा रूप से यह नहीं कह सकते हैं कि आप किस संशोधित संस्था को बचाना चाहते हैं।

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

मुझे लगता है कि हमें सर्वर परिदृश्य पर चर्चा करने की आवश्यकता नहीं है। बस कई HTTP अनुरोधों या वेब सेवा कॉल के बीच एकल इकाई साझा करने से आपका एप्लिकेशन बेकार हो जाता है। कोई भी अनुरोध केवल SaveChangesआंशिक डेटा को किसी अन्य अनुरोध से ट्रिगर और सहेज सकता है क्योंकि आप उन सभी के बीच काम की एकल इकाई साझा कर रहे हैं। इससे एक और समस्या भी होगी - संदर्भ और संदर्भ में संस्थाओं के साथ कोई हेरफेर या संदर्भ द्वारा उपयोग किया जाने वाला डेटाबेस कनेक्शन थ्रेड सुरक्षित नहीं है।

यहां तक ​​कि आसानी से एक आवेदन के लिए एक वैश्विक संदर्भ एक अच्छा विकल्प नहीं है क्योंकि आप शायद हर बार जब आप आवेदन को क्वेरी करते हैं तो ताजा डेटा चाहते हैं।


आपके जवाब के लिए धन्यवाद। शायद आप इस बात पर विस्तार से बता सकते हैं कि एक वैश्विक संदर्भ का उपयोग करना क्यों बुरा है? यह सुनिश्चित करने के लिए समानांतर उपयोग कठिन बनाता है, लेकिन और क्या ...?
नोल्डोरिन

ठीक है, यह अब बहुत स्पष्ट है, धन्यवाद। बस पुष्टि करने के लिए, हालांकि एक वैश्विक संदर्भ वास्तव में उपयुक्त नहीं है, "संवाद संपादित करें" या इस तरह का एक ही संदर्भ सही तरीका हो सकता है? अन्य स्थितियों में, वेब सेवाओं और ASP.NET की तरह, तरीकों के भीतर संदर्भ केवल अधिक समझ में आता है। सही के बारे में?
नौलडॉरिन

मैंने आपकी सलाह ली और सिंगेलटन को हटा दिया। अब मुझे एक और त्रुटि मिली: stackoverflow.com/questions/14795899/…
Elad Benda

मैं समझता हूं कि कार्य पैटर्न की इकाई को लागू करना और DbContext को एन्कैप करना व्यवसाय तर्क और डेटाबेस संचालन को अलग करना चाहिए। मैं यह समझने में सक्षम नहीं हूं कि कार्य पैटर्न की इकाई को कैसे लागू किया जाए और केवल कुछ कार्यों के लिए TransactionScope का उपयोग किया जाए।
रुडोल्फ ड्वोरसेक

4
@RudolfDvoracek: आसानी से। TransactionScopeकार्य की इकाई से संबंधित नहीं है, यह आपके व्यावसायिक तर्क से संबंधित है क्योंकि तर्क ही लेनदेन को परिभाषित करता है। कार्य की इकाई केवल यह परिभाषित करती है कि एक साथ क्या होना चाहिए, जबकि लेन-देन की गुंजाइश आपको एक ही लेनदेन के भीतर कई बार काम की दृढ़ता की इकाई का उपयोग करने की अनुमति देती है।
लद्देस्लाव मृका

70

डैनियल सीमन्स के अनुसार:

प्रत्येक सेवा पद्धति के लिए एक स्टेटमेंट का उपयोग करके एक नया ObjectContext उदाहरण बनाएं ताकि यह विधि के वापस आने से पहले ही निपट जाए। यह कदम आपकी सेवा की क्षमता के लिए महत्वपूर्ण है। यह सुनिश्चित करता है कि सेवा कॉल के दौरान डेटाबेस कनेक्शन खुले नहीं रखे जाते हैं और किसी विशेष ऑपरेशन द्वारा उपयोग किए जाने वाले अस्थायी राज्य में उस ऑपरेशन के समाप्त होने पर कचरा एकत्र किया जाता है। एंटिटी फ्रेमवर्क स्वचालित रूप से मेटाडेटा और अन्य जानकारी को ऐप डोमेन, और ADO.NET पूल डेटाबेस कनेक्शन में कैश करता है, इसलिए प्रत्येक बार संदर्भ को फिर से बनाना एक त्वरित ऑपरेशन है।

यह उनके व्यापक लेख से यहाँ है:

http://msdn.microsoft.com/en-us/magazine/ee335715.aspx

मेरा मानना ​​है कि यह सलाह HTTP अनुरोधों तक फैली हुई है, इसलिए ASP.NET के लिए मान्य होगी। एक स्टेटफुल, वसा-क्लाइंट एप्लिकेशन जैसे कि WPF एप्लिकेशन "साझा" संदर्भ के लिए एकमात्र मामला हो सकता है।


धन्यवाद, यह एक बहुत जानकारीपूर्ण उद्धरण है। हालाँकि, मैं अभी भी सोच रहा हूँ कि क्या एक साझा (वैश्विक) संदर्भ एक ग्राहक WPF ऐप या इस तरह के लिए भी उचित होगा। क्या इस मामले में भी कोई फायदा है?
नोल्डोरिन

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

1
सही; इतने अनिवार्य रूप से मैं कई अस्थायी संदर्भों का उपयोग करके वास्तव में गलत नहीं हो सकता (मुझे पता है कि कनेक्शन पूलिंग हो रहा है)? ... यदि आप एक एकल वैश्विक संदर्भ का उपयोग कर रहे थे, तो समय पर एक यादृच्छिक बिंदु पर सिद्धांत ड्रॉप में कनेक्शन नहीं हो सकता था?
नोल्डोरिन

1
@ नॉलोड्रिन: मुझे नहीं लगता कि कनेक्शन "बेतरतीब ढंग से" गिर जाएगा ... जोखिम यह है कि कनेक्शन को बहुत लंबा खुला रखा जा सकता है और कनेक्शन पूल को संतृप्त कर सकता है।
डेव स्वार्स्की

1
ObjectContext / DbContext लागू IDisposableहोना चाहिए, इसलिए कम से कम उचित समय के लिए खुला होना चाहिए, यह मेरा विचार है।
निकोडेमस 13

12

EF6 (4,5 भी) प्रलेखन के लिए प्रस्तुत करना: https://msdn.microsoft.com/en-us/data/hh949853#9

9.3 प्रति अनुरोध अनुरोध

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


2
मुझे पता है कि यह उत्तर यहां थोड़ी देर से आया है, लेकिन मुझे यह कहना है कि इससे मुझे एक टन सिरदर्द बचा है। ओरेकल के साथ ईएफ का उपयोग करते समय "पूल किए गए कनेक्शन" त्रुटि हो रही है, और समझ नहीं सका कि क्यों। मैंने dbContext को एक वर्ग चर के रूप में सेट किया था, जो इसे सृजन के समय तात्कालिक बनाता था। मेरी दुनिया के सभी विचारधाराओं को तय करने के लिए इसे संदर्भ में बदलना। धन्यवाद!
फ्लेचियस

1

नीचे दिए गए कोड ने मेरी वस्तु को नए डेटाबेस मूल्यों के साथ ताज़ा करने में मदद की। प्रविष्टि (ऑब्जेक्ट) .Reload () कमांड डेटाबेस मूल्यों को याद करने के लिए ऑब्जेक्ट को बाध्य करता है

GM_MEMBERS member = DatabaseObjectContext.GM_MEMBERS.FirstOrDefault(p => p.Username == username && p.ApplicationName == this.ApplicationName);
DatabaseObjectContext.Entry(member).Reload();

इसके साथ ही संग्रह (VB कोड) के लिए:CType(myContext, IObjectContextAdapter).ObjectContext.Refresh(RefreshMode.StoreWins,myCustomers)
Ivan Ferrer Villa
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.