2010-09-03 12 views
9

अस्वीकरण: मुझे पता है कि IDisposable अप्रबंधित संसाधनों से निपटने के दौरान लागू किया जाना चाहिए। बाकी कोड को यथासंभव शीघ्रता से गारंटी देने के लिए निर्धारक होना चाहिए और using (...) { } (try {} finally { Dispose(); } के समतुल्य) होना चाहिए। इसके अलावा, जीसी not call Dispose() होगा, इसलिए अनुशंसित पैटर्न Finalize() विधि (सी # में विनाशक वाक्यविन्यास का उपयोग करके) को ओवरराइड करना है, जो Dispose() पर कॉल करता है। जीसी आमतौर पर Finalize() (जब तक GC.SuppressFinalize() कहा जाता है) को कॉल नहीं किया जाएगा)।क्या एसक्यूएलकनेक्शन जीसी द्वारा निपटाया जाएगा?

समस्या: तो अब मुझे यह पता चला है कि मेरे पास एक अजीब परिदृश्य है जहां मैं अपने नियंत्रण से बाहर कोड के कारण using (SqlConnection...) { } नहीं कर सकता। मैं आमतौर पर एक निर्धारक Dispose() कर सकता हूं, लेकिन इसकी गारंटी नहीं दे सकता। मैंने SqlConnection को अलग करने के लिए परावर्तक का उपयोग किया और देखा कि यह निपटान() का उपयोग करता है, लेकिन जब तक कि मैं अंधा नहीं हूं तब तक कोई फाइनलाइज़र/विनाशक नहीं होता है (Finalize() या ~SqlConnection())। क्या इसका मतलब यह है कि जीसी अजीब मामले में कनेक्शन "साफ" (पूल पर वापस भेजना) नहीं करेगा? मैं कुछ भी निश्चित नहीं ढूंढ पाया है ...

उत्तर

7

ठीक है, यह निपटान नहीं किया जाएगा, क्योंकि अंतिमकरण निपटान नहीं है।

System.ComponentModel.Component में फाइनलर है, लेकिन इसे SQLConnection के कन्स्ट्रक्टर में दबाया गया है। यह एक अच्छा विचार है यदि आप किसी फाइनलजर के साथ कुछ प्राप्त करते हैं जिसे आप 100% निश्चितता के साथ जानते हैं जिसकी आपको आवश्यकता नहीं होगी, लेकिन अन्यथा एक बुरा विचार है। इस मामले में यह एक अच्छा विचार है।

हालांकि याद रखें, SqlConnection एक "वास्तविक" कनेक्शन पर एक रैपर है। दरअसल, यह ऑब्जेक्ट्स के एक बदलते सेट पर एक रैपर है जो विभिन्न कनेक्शन राज्यों का प्रतिनिधित्व करता है। यह उस तंत्र का हिस्सा है जो "वास्तविक" कनेक्शन को कुशलतापूर्वक पूल करने की अनुमति देता है, क्योंकि प्रत्येक बार जब आप Open() पर कॉल करते हैं तो यह पूल से प्रासंगिक वस्तु प्राप्त करता है, और हर बार जब आप Close() (सीधे, Dispose() पर या छोड़कर) using का दायरा) यह इसे वापस करता है।

अब, याद रखें कि केवल उन्हीं वस्तुओं को जो सीधे अप्रबंधित संसाधन या कुछ अन्य जीसी की चिंता नहीं रखते हैं, को अंतिम रूप देने की आवश्यकता है। SqlConnection एक ऑब्जेक्ट रखता है जो (SqlConnection की स्थिति के आधार पर) एक ऐसा हो सकता है जिसमें एक अप्रबंधित संसाधन (या वास्तव में, कक्षाओं के घोंसले के माध्यम से गहरा) हो। इसलिए SqlConnection को स्वयं को अंतिम रूप देने की आवश्यकता नहीं है। तीन संभावित तरीकों एक खुला SqlConnection एक खुला SqlConnection किया जा रहा रोक सकता है पर विचार करें:

  1. Close() कहा जाता है। यह तुरंत पूल से वास्तविक कनेक्शन देता है (या पूलिंग नहीं होने पर इसे बंद कर देता है)।
  2. Dispose() कहा जाता है। यह उसी प्रभाव के साथ Close() पर कॉल करता है।
  3. वस्तु को कचरा इकट्ठा किया जाता है।

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

तो SqlConnection एक finaliser था, केवल वास्तविक प्रभाव होगा:

  1. गाड़ी कोड के लिए संभावित (finaliser कोड में finalisable सदस्यों से निपटने भरा है, के रूप में आप नहीं जानते कि क्या है या नहीं वे है अंतिम रूप दिया गया)।
  2. चीजों को धीमा (वास्तविक संबंध में सबसे अच्छा हम सिर्फ अंतिम रूप दिए जाने और जीसी अप धीमा कर रहे हैं वैसे भी अंतिम रूप दिया जा रहा है,) के लिए संभावित। यहां वैसे भी ऐसा करने के लिए
  3. कुछ भी नहीं है (वास्तविक संबंध किसी भी मदद के लिए यहाँ बिना अंतिम रूप दिया जाएगा)।

तो, SqlConnection पर फाइनलर डालने के बिना जीत के बिना हार जाती है। साथ ही, आपका असली कनेक्शन उम्मीद है कि आखिर में अंतिम रूप दिया जाना चाहिए।

यह कहा गया है कि यह अभी भी आदर्श से दूर है और अभी भी बहुत कनेक्शन रिसाव की संभावना है। क्या आप विस्तार से बता सकते हैं कि आप Close() पर कॉल क्यों नहीं कर सकते हैं या खुद का निपटान नहीं कर सकते? कोड कनेक्शन के प्रबंधन आप के लिए पास फोन नहीं किया जा सका (वस्तु अपने दिनों कहीं खत्म होना चाहिए, और वहाँ बंद किया जाना चाहिए)?

क्या आपको इसे IDataReader या किसी ऑब्जेक्ट को IDataReader से पूरा करने की अनुमति देने के लिए ज़िंदा रखने की आवश्यकता है? किस मामले में, क्या आप CommandBehavior.CloseConnection ध्वज का उपयोग कर सकते हैं ताकि पाठक बंद (या निपटान) कनेक्शन बंद कर दे? यह बाद का मामला एकमात्र मामला है जहां मुझे कभी भी एक कनेक्शन छोड़ने के लिए बिना किसी निपटारे को छोड़ने के लिए याद किया जा सकता है।

+0

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

+0

उसे सुनकर खुशी हुई। अंतिम रूप दिए जाने की बात सब कुछ ठीक है और अच्छा है सही वस्तु पर किया जा रहा है, लेकिन अगर अंतिम रूप देने के लिए अक्सर पर्याप्त नहीं होता है (और IME यह लगभग कभी नहीं करता आप मदद नहीं करेगा - या बुरा भी बदतर, यह परीक्षण में नहीं है और जीना)। –

+0

+1 अच्छा जवाब। मैं एमएसडीएन पर निम्नलिखित कथन के बारे में थोड़ा उलझन में हूं जो बताता है कि एसक्यूएलकनेक्शन एक प्रबंधित संसाधन है। "अपनी कक्षा के अंतिम रूप में एक कनेक्शन, एक डेटा रीडर, या किसी अन्य ** प्रबंधित ** ऑब्जेक्ट पर बंद या निपटान न करें।" [यहां] से (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.close%28v=vs.110%29.aspx) –

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