2009-10-12 24 views
5

विधि को देखते हुए:एसक्यूएलकनेक्शन का निपटारा/बंद क्यों नहीं किया गया है?

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"]); 
    SqlCommand sqlcmd = sqlc.CreateCommand(); 
    sqlcmd.CommandText = commandText; 
    var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
    adapter.Fill(dataset); 


    return dataset; 
} 

क्यों sqlc (SqlConnection) निपटारा नहीं किया गया है के बाद/बंद बुला विधि के दायरे या sqlc कोई और अधिक संदर्भ होते हैं बाहर चला जाता है?

संपादित करें 1: भी उपयोग करने में यह लपेटकर, मैं अभी भी का उपयोग कर कनेक्शन (मैं है कनेक्शन पूलिंग बंद कर दिया) देखकर कर सकते हैं:

SELECT DB_NAME(dbid) as 'Database Name', 
COUNT(dbid) as 'Total Connections' 
FROM sys.sysprocesses WITH (nolock) 
WHERE dbid > 0 
GROUP BY dbid 

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

उत्तर

19

सी # के कचरा संग्रहण गैर नियतात्मक है, लेकिन भाषा इस तरह संसाधन निपटान के लिए एक नियतात्मक संरचना प्रदान करता है:

using (SqlConnection connection = new SqlConnection(...)) 
{ 
    // ... 
} 

यह एक try/finally ब्लॉक जो यह सुनिश्चित करेंगे कि कनेक्शन वस्तु परवाह किए बिना का निपटारा किया जाता है पैदा करेगा क्या विधि में होता है। आपको वास्तव में इस तरह के किसी भी ब्लॉक में IDisposable को लागू करने वाले प्रकारों के किसी भी उदाहरण को लपेटना चाहिए क्योंकि यह जिम्मेदारी संसाधन प्रबंधन (डेटाबेस कनेक्शन जैसे अप्रबंधित संसाधनों) सुनिश्चित करेगा और यह आपको निर्धारित निर्धारक नियंत्रण भी प्रदान करेगा।

+0

+1 साफ जवाब के लिए, मेरे से बेहतर। –

1

कचरा संग्रह के बाद यह काम करेगा। इसे बंद किए बिना लिखने के लिए फ़ाइल स्ट्रीम खोलने के लिए भी चला जाता है। कोड को दायरे से बाहर होने के बावजूद इसे 'लॉक' किया जा सकता है।

2

क्योंकि सी # एक कचरा एकत्रित भाषा है, और कचरा संग्रह निर्धारित नहीं है। इसका तथ्य यह है कि आपका वर्ग कनेक्शन निपटाया गया है। आप बस कब चुनने के लिए नहीं मिलता है।

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

internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    using (SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) 
    using (SqlCommand sqlcmd = sqlc.CreateCommand()) 
    { 
     sqlcmd.CommandText = commandText; 
     var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
     adapter.Fill(dataset); 

    } 
    return dataset; 
} 

हालांकि क्योंकि .Fill() method is a strange beast:

IDbConnection भरण से पहले बंद कर दिया जाता है, तो कहा जाता है, यह डेटा पुनः प्राप्त करने खोला जाता है और फिर बंद कर दिया।

तो इसका मतलब है कि अगर आप एक बंद कनेक्शन से शुरू करते हैं तो डेटा एडाप्टर को आपके लिए इसका ख्याल रखना चाहिए। मैं बहुत चिंतित हूं कि आप अपने एसक्यूएल कमांड में एक सादे स्ट्रिंग के रूप में गुजर रहे हैं। समय-समय पर आपके प्रश्नों में उपयोगकर्ता पैरामीटर होना चाहिए, और इसका मतलब है कि आप उस डेटा को सीधे कमांड स्ट्रिंग में जोड़ रहे हैं। ऐसा मत करो !! इसके बजाय SqlCommand के पैरामीटर संग्रह का उपयोग करना।

1

मुझे विश्वास है कि एसक्यूएलकनेक्शन पूलिंग के साथ इसका कुछ संबंध है।आप क्या कर सकते हैं, और हम अक्सर काम पर पूरे कॉल को एक कथन कथन में लपेटते हैं जो इसे निपटान() विधि को कॉल करने का कारण बनता है, कनेक्शन को बंद कर देता है और ऑब्जेक्ट का निपटान

आप ऐसा कुछ कर सकते हैं इसके बदले:


internal static DataSet SelectDataSet(String commandText, DataBaseEnum dataBase) 
{ 
    var dataset = new DataSet(); 

    using(SqlConnection sqlc = dataBase == DataBaseEnum.ZipCodeDb 
          ? new SqlConnection(ConfigurationManager.AppSettings["ZipcodeDB"]) 
          : new SqlConnection(ConfigurationManager.AppSettings["WeatherDB"])) { 
     SqlCommand sqlcmd = sqlc.CreateCommand(); 
     sqlcmd.CommandText = commandText; 
     var adapter = new SqlDataAdapter(sqlcmd.CommandText, sqlc); 
     adapter.Fill(dataset); 


     return dataset; 
    } 
} 

1

मैं यहां सभी उत्तरों से सहमत हूं और एक कनेक्शन सिर्फ एक विधि से अधिक व्यापक दायरा हो सकता है। जब आपको विभिन्न स्थानों में अपने मौजूदा कनेक्शन का उपयोग करने की आवश्यकता होती है तो परिदृश्य थोड़ा बदल जाता है। को उन सभी ऑब्जेक्ट्स के लिए हमेशा Dispose पर कॉल करना सुनिश्चित करें जो आपके द्वारा किए जाने के बाद IDisposable लागू करते हैं। यह एक अच्छा अभ्यास है ताकि आप अप्रयुक्त वस्तुओं के साथ समाप्त न हों कि कचरा कलेक्टर यह तय नहीं कर सकता कि उनके साथ क्या किया जाए।

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