2011-10-27 12 views
9

का निपटान करने का सही तरीका है, मैं सोच रहा था कि मेरा नीचे कार्यान्वयन इस मामले में SQLconnection का निपटान करने का सबसे प्रभावी तरीका है या नहीं।क्या यह SQLConnection

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

public class SqlRepository : IRepository 
{ 
    private readonly string connectionString; 
    private SqlConnection connection; 

    public SqlRepository(string connectionString) 
    { 
     this.connectionString = connectionString; 
     connection = new SqlConnection(connectionString); 
     connection.Open(); 
    } 

    public void Method_A() 
    { 
     // uses the SqlConnection to fetch data 
    }  

    public void Method_B() 
    { 
     // uses the SqlConnection to fetch data 
    }  

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

उपयोग:

using (IRepository repository = new SqlRepository(connectionString)) 
{ 
    var item = repository.items;  
} 

अद्यतन IRepository IDisposable

+0

हालांकि इसकी लगभग हां, लेकिन ब्लॉक का उपयोग करने में कनेक्शन खोलने के बाद अपवाद के मामले में, यदि आप अधिक परिचालन करते हैं तो कुछ अपवाद फेंकने से आपकी कनेक्शन ऑब्जेक्ट कभी निपटान नहीं होगी। और कनेक्शन ऑब्जेक्ट्स को वैश्विक दायरा बनाने का अच्छा विचार नहीं है, इसके बजाए कमांडबैवियर के साथ खेलें यहां देखें: http://stackoverflow.com/questions/7903326/why-does-my-sccessccess-read-npgsql-data-disappear/7903616 # 7903616 – Zenwalker

+0

एक और युक्ति है, हमेशा दिशानिर्देशों का पालन करें और निपटान पैटर्न लागू करें। और कनेक्शन। मान लें() आपके लिए कनेक्शन बंद कर देगा, आप इसकी आईएल देख सकते हैं और आप डीबीसी कनेक्शन देखेंगे। (कॉल) को कॉल किया जा रहा है। तो उपयोग() {} के तहत कॉन खोलना पर्याप्त है बशर्ते कोई अपवाद फेंक दिया न जाए। – Zenwalker

+0

@zenwalker '... बशर्ते कोई अपवाद नहीं फेंक दिया गया है 'कथन का उपयोग कर' की मेरी समझ यह है कि इसे कंपाइलर द्वारा 'try' /' अंत में' में अनुवादित किया जाता है, इसलिए इसे हमेशा किसी मामले के मामले में भी निपटाया जाता है अपवाद। –

उत्तर

9

कनेक्शन को खुली अवधि में कॉल न रखें। आप कनेक्शन पूलिंग को हरा रहे हैं।

यदि आप पूल किए गए कनेक्शन (एसक्लसेवरर) के साथ काम कर रहे हैं, तो यह पूल और पुन: उपयोग करेगा। विधि के भीतर बस खोलें और बंद करें & बी।

आप तर्क दे सकते हैं कि अगर कॉलर एक विधि कॉल के साथ उपयोग करने के साथ करता है तो यह ठीक है। लेकिन यदि आप प्रत्येक कार्यकर्ता विधि (1) के अंदर sqlconnection के साथ {} का उपयोग करते हैं तो कोड सरल होगा और (2) आपको यह सुनिश्चित किया जाता है कि पूलिंग को पराजित नहीं किया जाएगा (जिसका मतलब है कि आपके होल्डिंग आइटम पूलिंग से बाहर हैं जब अन्य अनुरोध इसका उपयोग कर सकते हैं) ।

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

टिप्पणी के आधार पर छद्म जोड़ा जा रहा है।

पैटर्न समस्याग्रस्त है क्योंकि एक कॉलर कर सकता है।

//pseudo code 
using (SqlRepository r) 
{ 
    r.MethodA(); 

    // other code here that takes some time. your holding a connection 
    // out of the pool and being selfish. other threads could have 
    // used your connection before you get a chance to use it again. 

    r.MethodB(); 
} // freed for others here. 

जो सर्वर की स्केलेबिलिटी को मार देगा - मेरा विश्वास करो। मैंने देखा है कि बहुत बड़ी प्रणालियों को इस तरह से दबाया जाता है - आम तौर पर क्योंकि वे एटी साइड लेनदेन कर रहे हैं।

एक बेहतर पैटर्न:

class Repository 
{ 
    void MethodA() 
    { 
     using (Sqlconnection) 
     { 
      // db call 
     } 
    } 

    void MethodB() 
    { 
     using (Sqlconnection) 
     { 
      // you can even have multiple calls here (roundtrips) 
      // and start transactions. although that can be problematic 
      // for other reasons. 
     } 
    } 

अब, पूल सबसे प्रभावी है। मुझे एहसास है कि सवाल डिस्पोजेबल पैटर्न पर था - और हाँ आप इसे कर सकते हैं। लेकिन ...

मैं कनेक्शन को भंडार के जीवनकाल तक नहीं पहुंचूंगा। IDisposable से

+1

'शायद' - यदि आप लेनदेन समर्थन चाहते हैं तो आपके पास इसे खोलने का एक कारण हो सकता है। बंद कनेक्शन कनेक्शन का समर्थन नहीं करेंगे। रिपोजिटरीज कभी-कभी किसी अन्य वर्ग (संदर्भ, इत्यादि) को इंजेक्ट/निर्माण करेंगे जिसका उपयोग कई रिपॉजिटरीज़ (काम के साथ या बिना) पर किया जा सकता है –

+0

ठीक है - हालांकि एसक्यूएल में लेनदेन का विकल्प होगा। एक डीटीसी टीएक्स पर पूल अवरुद्ध करने से कनेक्शन को पकड़ना एक कारण हो सकता है लेकिन जब तक आपको पूरी तरह से नहीं करना पड़ता है तब तक बड़ी कमी होती है। प्वाइंट लिया गया लेकिन मुझे उसमें मजबूर होना होगा :) – bryanmac

+0

लेनदेन एक क्रॉस काटने की चिंता है और पूरी तरह से आवश्यक होने तक imho सामान्य रूप से एसक्यूएल पक्ष पर नहीं है। कोड किसी कारण से इसका समर्थन करता है, और कोड को पता होना चाहिए कि एक बार में क्या सहेजा जाना चाहिए। यदि यह एसक्यूएल सर्वर पक्ष पर जाता है, तो आप डीबी पक्ष पर तर्क शामिल करने का निर्धारण कर रहे हैं जो इकाई परीक्षण करते समय जटिल हो जाना शुरू कर देता है। मेरे विचार वैसे भी:) –

0

लागू आप ऐसा करना चाहते हैं, तो आप IDisposable को लागू (मैं अगर आप ध्यान दें नहीं कर सकते बता सुनिश्चित करता है यह आपके आईआरपॉजिटरी इंटरफेस पर है या नहीं) और मैं कुछ ऐसा करूंगा:

 

     private bool disposed = false; 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!this.disposed) 
      { 
       if (disposing) 
       { 
        _context.Dispose(); 
       } 
      } 
      this.disposed = true; 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
      GC.SuppressFinalize(this); 
     } 

स्पष्ट रूप से _context यहां आपका एसक्यूएलकनेक्शन है।

हालांकि - क्या आप वाकई प्रति भंडार एक कनेक्शन चाहते हैं? एक से अधिक भंडार फैलाने वाले संचालन के बारे में क्या?

+0

यह एक बेहतर डिस्पोजेबल पैटर्न है लेकिन सवाल यह है कि कनेक्शन को कॉल के दौरान कनेक्शन कब खुलासा किया जाना चाहिए, जब अन्य अनुरोध उस कनेक्शन का पुन: उपयोग कर सकते हैं – bryanmac

+0

मुझे लगता है कि आप प्रति प्रश्न 1 कनेक्शन पर इस प्रश्न पर संकेत दे रहे थे ... समवर्ती सेवा – bryanmac

+0

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

0

मान लिया जाये कि IRepository इनहेरिट करती है, अपने कार्यान्वयन ठीक आप अपने SqlRepository वर्ग लंबे समय तक की तुलना में यह डेटाबेस पर प्रश्नों की एक 'तार्किक' अनुक्रम प्रदर्शन करने के लिए ले जाता है के लिए खुला का एक उदाहरण रखते हुए नहीं कर रहे हैं प्रदान की जाती है।तथ्य यह है कि यह अनुक्रम कई विधि कॉलों का विस्तार कर सकता है कोई समस्या नहीं है।

मैं @ bryanmac के जवाब से असहमत:

कनेक्शन खुला स्पैनिंग कॉल न रखें। आप कनेक्शन पूलिंग को हरा रहे हैं।

विधि कॉल के अपने अनुक्रम परंतु साथ रहती हैं, और आप कनेक्शन लंबे समय तक के लिए खुला नहीं रखते यह तार्किक अनुक्रम पूरा करने के लिए ले जाता है की तुलना में, मैं देख नहीं है किसी भी तरह से यह कैसे धरा कनेक्शन पूलिंग।

हालांकि एक टिप्पणी। आपको:

  • या तो मानक IDisposable पैटर्न (एक protected void Dispose(bool disposing) विधि है कि व्युत्पन्न वर्ग

  • या अपने वर्ग सील कर में अधिरोहित जा सकता है के साथ, ऐसी स्थिति में अपने मौजूदा IDisposable कार्यान्वयन ठीक है को लागू

+0

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

+0

कहकर आप एक उपयोग ब्लॉक में लगातार कॉल को लपेटकर पूलिंग समस्या से बचेंगे - आप कह रहे हैं कि आप हमेशा छोटे से दायरे को कम करके और वापस कॉल करके प्रभाव को कम कर देंगे। समय के साथ कोड बदल जाएगा - अपने कोड को सुनिश्चित न करें। कनेक्शन पूल को सुनिश्चित करें कि कनेक्शन कुशलता से उपयोग किए जा रहे हैं ... – bryanmac

+0

आप कह रहे हैं कि यह "प्रदान करने ..." और "जब तक ..." समस्या नहीं होगी। समस्या यह है कि आप कह सकते हैं कि जब तक आपके भंडारकर्ता के कॉलर्स कुछ चीजें नहीं करते हैं तब तक यह समस्याग्रस्त नहीं होगा। पर क्यों? आपके भंडार के जीवनकाल में कनेक्शन को किस प्रकार पहुंचाया जा रहा है? यह आपको एक शांत डिस्पोजेबल पैटर्न को लागू करने की अनुमति देता है और यह इसके बारे में है। यदि आप प्रत्येक विधि में एसक्यूएलकनेक्शन का दायरा रखते हैं, तो पूल आपके * सबसे * कुशल सुनिश्चित करेगा क्योंकि प्रत्येक कनेक्शन का उपयोग दानेदार है। यदि आप कॉल का अनुक्रम बनाते हैं तो पूल सुनिश्चित करेगा कि आप अच्छे हैं। – bryanmac

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