क्या SqlDataReader को मैन्युअल रूप से बंद करना और निपटाना आवश्यक है?


90

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

क्या इससे प्रदर्शन में सुस्ती आ सकती है?

जवाबों:


125

इस तरह से पाठकों का उपयोग करने से बचने की कोशिश करें:

SqlConnection connection = new SqlConnection("connection string");
SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection);
SqlDataReader reader = cmd.ExecuteReader();
connection.Open();
if (reader != null)
{
      while (reader.Read())
      {
              //do something
      }
}
reader.Close(); // <- too easy to forget
reader.Dispose(); // <- too easy to forget
connection.Close(); // <- too easy to forget

इसके बजाय, उन्हें बयानों का उपयोग करके लपेटें:

using(SqlConnection connection = new SqlConnection("connection string"))
{

    connection.Open();

    using(SqlCommand cmd = new SqlCommand("SELECT * FROM SomeTable", connection))
    {
        using (SqlDataReader reader = cmd.ExecuteReader())
        {
            if (reader != null)
            {
                while (reader.Read())
                {
                    //do something
                }
            }
        } // reader closed and disposed up here

    } // command disposed here

} //connection closed and disposed here

उपयोग कथन वस्तु के सही निपटान और संसाधनों को मुक्त करने को सुनिश्चित करेगा।

यदि आप भूल जाते हैं, तो आप कचरा कलेक्टर तक सफाई छोड़ रहे हैं, जिसमें कुछ समय लग सकता है।


24
आपको नमूना में .Close () कथन की आवश्यकता नहीं है: यह .Dispose () कॉल द्वारा नियंत्रित किया जाता है।
जोएल कोएहॉर्न

7
शायद यह जाँच करना चाहते हैं कि यह .HRRows बल्कि फिर अशक्त।
जोन्ह

3
@ और अगर ExecuteReader एक अपवाद फेंकता है, तो यह अशक्त कैसे लौट सकता है?
csauve

7
@ जौह: जबकि (पाठक। रीड ()) उदाहरण में .HasRows के समान है, और आपको पहली पंक्ति के आगे पाठक को आगे बढ़ाने के लिए किसी भी तरह की आवश्यकता है।
csauve

1
@csauve तुम सही हो, मुझे लगता है कि यह अशक्त नहीं लौटा है। मुझे यकीन नहीं है कि मैं SqlDataReader चर के मूल्य को क्यों देख रहा था।
एंड्रयू

53

ध्यान दें कि SqlDataReader का निपटान SqlCommand.ExecuteReader () का उपयोग करके तत्काल किया गया है जो अंतर्निहित कनेक्शन को बंद / बंद नहीं करेगा ।

दो सामान्य पैटर्न हैं। पहले में, पाठक को कनेक्शन के दायरे में खोला और बंद किया जाता है:

using(SqlConnection connection = ...)
{
    connection.Open();
    ...
    using(SqlCommand command = ...)
    {
        using(SqlDataReader reader = command.ExecuteReader())
        {
            ... do your stuff ...
        } // reader is closed/disposed here
    } // command is closed/disposed here
} // connection is closed/disposed here

कभी-कभी डेटा एक्सेस पद्धति का कनेक्शन खोलना और रीडर को वापस करना सुविधाजनक होता है। इस मामले में यह महत्वपूर्ण है कि लौटा हुआ रीडर CommandBehavior.CloseConnection का उपयोग करके खोला जाता है, ताकि पाठक को बंद करना / निपटाना अंतर्निहित कनेक्शन को बंद कर दे। पैटर्न कुछ इस तरह दिखता है:

public SqlDataReader ExecuteReader(string commandText)
{
    SqlConnection connection = new SqlConnection(...);
    try
    {
        connection.Open();
        using(SqlCommand command = new SqlCommand(commandText, connection))
        {
            return command.ExecuteReader(CommandBehavior.CloseConnection);
        }
    }
    catch
    {
        // Close connection before rethrowing
        connection.Close();
        throw;
    }
}

और कॉलिंग कोड को पाठक को निपटाने की जरूरत है:

using(SqlDataReader reader = ExecuteReader(...))
{
    ... do your stuff ...
} // reader and connection are closed here.

दूसरे कोड स्निपेट में, जहां विधि एक SqlDataReader देता है, कमांड निपटाया नहीं जाता है। क्या यह ठीक है और कमांड को निपटाना (इसे एक ब्लॉकिंग ब्लॉक में संलग्न करना) और फिर पाठक को वापस करना ठीक है?
हमेशा

@alwayslearning यह बिल्कुल ऐसा परिदृश्य है जो मेरे पास है …… क्या आप SqlCommand को बंद कर सकते हैं / जब आप कॉल करने वाले को SqlDataReader लौटा रहे हैं?
गांडर्स

1
ये गलत है। यदि आप वास्तव मेंusing एस का उपयोग करने के लिए सहन नहीं कर सकते, तो कॉल finally {}को पकड़ने के बाद ब्लॉक में निपटान करें । जिस तरह से यह लिखा गया है, सफल आदेशों को कभी भी बंद या निपटाया नहीं जाएगा।
smdrager

2
@smdrager, यदि आप उत्तर को करीब से पढ़ते हैं, तो वह एक विधि के बारे में बात कर रहा है जो एक पाठक को लौटाता है। यदि आप उपयोग करते हैं .ExecuteReader (CommandBehavior.CloseConnection); फिर READER को निपटाने के बाद, कनेक्शन बंद हो जाएगा। इसलिए कॉलिंग विधि को केवल एक उपयोग कथन में परिणामी रीडर को लपेटने की आवश्यकता है। उपयोग (var rdr = SqlHelper.GetReader ()) {// ...} यदि आप इसे अंत में बंद कर रहे थे, तो आपका पाठक पढ़ने में विफल रहेगा क्योंकि कनेक्शन बंद है।
सिनास्टैटिक

@ वांडर्स - इस पुरानी पोस्ट पर वापस आना: हाँ आप कर सकते हैं और शायद SqlCommand को निपटाना चाहिए - ऐसा करने के लिए उदाहरण को अपडेट किया।
जो

11

सुरक्षित होने के लिए, एक उपयोग कथन में प्रत्येक SqlDataReader ऑब्जेक्ट को लपेटें ।


काफी उचित। हालांकि, क्या यह वास्तव में प्रदर्शन में कोई अंतर है अगर कोई बयान का उपयोग नहीं करता है?
जॉन ओब्बी

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

यह मेरे द्वारा दिए गए लिंक से सीधे है: "उपयोग कथन यह सुनिश्चित करता है कि ऑब्जेक्ट पर कोई कॉल करते समय अपवाद तब भी होता है जब कोई अपवाद उत्पन्न होता है।"
कोन

5
जारी ... "आप एक प्रयास ब्लॉक के अंदर ऑब्जेक्ट डालकर और फिर अंत में ब्लॉक में डिस्पोज को बुलाकर एक ही परिणाम प्राप्त कर सकते हैं, वास्तव में, यह है कि संकलक द्वारा उपयोग किए गए कथन का अनुवाद किया गया है।"
कोन

5

बस अपने SQLDataReader को "उपयोग" कथन के साथ लपेटें। आपको अपने अधिकांश मुद्दों का ध्यान रखना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.