"उपयोग" ब्लॉक में एक SqlConnection रिटर्न या अपवाद पर बंद है?


136

पहला प्रश्न:
कहो मेरे पास है

using (SqlConnection connection = new SqlConnection(connectionString))
{
    connection.Open();

    string storedProc = "GetData";
    SqlCommand command = new SqlCommand(storedProc, connection);
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));

    return (byte[])command.ExecuteScalar();
}

क्या कनेक्शन बंद हो गया? क्योंकि तकनीकी }रूप से हम returnउससे पहले कभी भी अंतिम रूप में नहीं पहुंचते हैं।

दूसरा सवाल:
इस बार मेरे पास है:

try
{
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        int employeeID = findEmployeeID();

        connection.Open();
        SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
        command.CommandTimeout = 5;

        command.ExecuteNonQuery();
    }
}
catch (Exception) { /*Handle error*/ }

अब, tryहम कहते हैं कि कहीं हम एक त्रुटि प्राप्त करते हैं और यह पकड़ा जाता है। क्या अब भी कनेक्शन बंद है? क्योंकि फिर से, हम बाकी कोड को छोड़ देते tryहैं और सीधे catchस्टेटमेंट पर जाते हैं।

मैं कैसे usingकाम करता है में बहुत रैखिक सोच रहा हूँ ? Dispose()जब हम usingस्कोप छोड़ते हैं तो क्या केवल कॉल किया जाता है?

जवाबों:


178
  1. हाँ
  2. हाँ।

किसी भी तरह से, जब उपयोग ब्लॉक से बाहर निकल जाता है (या तो सफल समापन या त्रुटि के द्वारा) इसे बंद कर दिया जाता है।

हालांकि मुझे लगता है कि इस तरह का आयोजन करना बेहतर होगा क्योंकि यह देखना बहुत आसान है कि क्या होने वाला है, यहां तक ​​कि नए रखरखाव प्रोग्रामर के लिए भी जो बाद में इसका समर्थन करेंगे:

using (SqlConnection connection = new SqlConnection(connectionString)) 
{    
    int employeeID = findEmployeeID();    
    try    
    {
        connection.Open();
        SqlCommand command = new SqlCommand("UpdateEmployeeTable", connection);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));
        command.CommandTimeout = 5;

        command.ExecuteNonQuery();    
    } 
    catch (Exception) 
    { 
        /*Handle error*/ 
    }
}

3
@TrueWill - मैं सहमत हूं। मैंने संरचना के लिए कोड को थोड़ा सा इधर-उधर कर दिया।
डेविड

10
प्रश्न: क्या यूज़िंग स्टेटमेंट का उपयोग करते समय मुझे कनेक्शन खोलने की आवश्यकता है?
68

3
इसके अलावा, यदि आप लेन-देन का उपयोग कर रहे हैं, तो आपके try catchभीतर होने से usingस्पष्ट रूप से .Commitया .Rollbackलेन-देन हो सकता है catch। यह अधिक पठनीय और स्पष्ट दोनों है, और आपको यह प्रतिबद्ध करने के लिए अनुमति देता है कि यदि अपवाद के प्रकार को देखते हुए समझ में आता है। (लेन-देन अंतर्निहित रूप से वापस किए जाने पर conn.Closeप्रतिबद्ध नहीं है।)।
क्रिस 18

8
@ फर्नांडो68 हां, आपको अभी भी Openकनेक्शन देना है। usingकेवल इस बात की गारंटी देता है कि ऑब्जेक्ट की Disposeविधि को कहा जाता है।
जुखर

मैं ब्लॉक का उपयोग कर अंदर ExecuteScalar लौटा है। और जब मैं दूसरी बार विधि चलाता हूं तो यह बहुत जल्दी होता है, जैसे कनेक्शन खुला था। क्यों यह दूसरी बार इतनी जल्दी है?
सकारात्मक दृष्टिकोण

46

दोनों सवालों के लिए हाँ। उपयोग कथन एक कोशिश / अंत में ब्लॉक में संकलित हो जाता है

using (SqlConnection connection = new SqlConnection(connectionString))
{
}

के समान है

SqlConnection connection = null;
try
{
    connection = new SqlConnection(connectionString);
}
finally
{
   if(connection != null)
        ((IDisposable)connection).Dispose();
}

संपादित करें: कलाकारों को डिस्पोजेबल http://msdn.microsoft.com/en-us/library/yh598w02.aspx पर फिक्सिंग


यह वास्तव में ऐसा नहीं है, लेकिन यह काफी करीब है। सटीक अंतर महत्वपूर्ण नहीं है।
ब्रायन

@ ब्रायन नहीं मिला, क्या आप कृपया सटीक अंतर का उल्लेख कर सकते हैं, हमें और अधिक दुबला करने में मदद कर सकता है :-)
mohits00691

वाह, यह एक टिप्पणी थी जो बहुत समय पहले हुई थी :) ऐसा लगता है जैसे मैंने उस टिप्पणी के बाद एक दिन संपादित किया था। मुझे लगता है कि यही वह अंतर है जिसके बारे में मैं सोच रहा था।
ब्रायन

@ ब्रायन हां, मैंने आपकी टिप्पणी के बाद समायोजन को ठीक कर दिया है।
रयान पेडरसन

17

यहाँ मेरा टेम्पलेट है। सब कुछ आप एक SQL सर्वर से डेटा का चयन करने की आवश्यकता है। कनेक्शन को बंद कर दिया जाता है और कनेक्शन और निष्पादन में त्रुटियां पकड़ी जाती हैं।

string connString = System.Configuration.ConfigurationManager.ConnectionStrings["CompanyServer"].ConnectionString;
string selectStatement = @"
    SELECT TOP 1 Person
    FROM CorporateOffice
    WHERE HeadUpAss = 1 AND Title LIKE 'C-Level%'
    ORDER BY IntelligenceQuotient DESC
";
using (SqlConnection conn = new SqlConnection(connString))
{
    using (SqlCommand comm = new SqlCommand(selectStatement, conn))
    {
        try
        {
            conn.Open();
            using (SqlDataReader dr = comm.ExecuteReader())
            {
                if (dr.HasRows)
                {
                    while (dr.Read())
                    {
                        Console.WriteLine(dr["Person"].ToString());
                    }
                }
                else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
            }
        }
        catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
        if (conn.State == System.Data.ConnectionState.Open) conn.Close();
    }
}

* संशोधित: 2015-11-09 *
जैसा कि NickG द्वारा सुझाया गया है; यदि बहुत सारे ब्रेसिज़ आपको परेशान कर रहे हैं, तो प्रारूप इस तरह ...

using (SqlConnection conn = new SqlConnection(connString))
   using (SqlCommand comm = new SqlCommand(selectStatement, conn))
   {
      try
      {
         conn.Open();
         using (SqlDataReader dr = comm.ExecuteReader())
            if (dr.HasRows)
               while (dr.Read()) Console.WriteLine(dr["Person"].ToString());
            else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)");
      }
      catch (Exception e) { Console.WriteLine("Error: " + e.Message); }
      if (conn.State == System.Data.ConnectionState.Open) conn.Close();
   }

तो फिर, अगर आप ईए या डेब्रेक गेम के लिए काम करते हैं, तो आप किसी भी लाइन-ब्रेक को भी रोक सकते हैं क्योंकि वे सिर्फ उन लोगों के लिए हैं जिन्हें वापस आना है और बाद में आपके कोड को देखना है और कौन वास्तव में परवाह करता है? क्या मैं सही हू? मेरा मतलब है कि 23 के बजाय 1 लाइन का मतलब है कि मैं एक बेहतर प्रोग्रामर हूं, है ना?

using (SqlConnection conn = new SqlConnection(connString)) using (SqlCommand comm = new SqlCommand(selectStatement, conn)) { try { conn.Open(); using (SqlDataReader dr = comm.ExecuteReader()) if (dr.HasRows) while (dr.Read()) Console.WriteLine(dr["Person"].ToString()); else Console.WriteLine("No C-Level with Head Up Ass Found!? (Very Odd)"); } catch (Exception e) { Console.WriteLine("Error: " + e.Message); } if (conn.State == System.Data.ConnectionState.Open) conn.Close(); }

भई ... ठीक है। मैं अपने सिस्टम से बाहर हो गया और थोड़ी देर के लिए खुद को खुश कर रहा हूं। लगे रहो।


6
क्या आप जानते हैं कि आप अतिरिक्त ब्रेसिज़ के बिना बयानों का उपयोग कर सकते हैं? अंतिम ब्रेस को हटाएं, फिर एक दूसरे के बगल में स्टेटमेंट का उपयोग करें :)
NickG

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

आप conn.Close();आखिर में उपयोग क्यों करते हैं ? usingबयान नहीं करता है कि आप के माध्यम से निपटान के लिए?
फ्रेड्रिक गॉस

मेरा मानना ​​है कि यह अब (.net 3.5 से) करता है। यह .net 2.0 के साथ मेरे लिए जल्दी स्पष्ट नहीं था इसलिए मैंने इसे जांचना और बंद करने की आदत बना ली।
शेनसेल

1
"23 के बजाय 1 लाइन का मतलब है कि मैं एक बेहतर प्रोग्रामर हूं, है ना?" मुझे आप पसंद हैं :-D
फिलिप मुलर

5

डिस्पोज़ बस तब कहलाता है जब आप उपयोग करने की गुंजाइश छोड़ देते हैं। "का उपयोग करना" का उद्देश्य डेवलपर्स को यह सुनिश्चित करने के लिए एक गारंटीकृत तरीका देना है कि संसाधनों का निपटान हो।

से MSDN :

एक उपयोग कथन को या तो तब बाहर किया जा सकता है जब उपयोग कथन के अंत तक पहुँच जाता है या यदि कोई अपवाद फेंक दिया जाता है और नियंत्रण कथन के अंत से पहले स्टेटमेंट ब्लॉक छोड़ देता है।


5

Usingआवंटित किए जा रहे ऑब्जेक्ट के चारों ओर / अंततः एक कोशिश करता है और Dispose()आपके लिए कॉल करता है।

यह आपको मैन्युअल रूप से कोशिश / अंत में ब्लॉक करने और कॉल करने की परेशानी से बचाता है Dispose()


3

आपके पहले उदाहरण में, C # संकलक वास्तव में निम्नलिखित के लिए उपयोग कथन का अनुवाद करेगा:

SqlConnection connection = new SqlConnection(connectionString));

try
{
    connection.Open();

    string storedProc = "GetData";
    SqlCommand command = new SqlCommand(storedProc, connection);
    command.CommandType = CommandType.StoredProcedure;
    command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));

    return (byte[])command.ExecuteScalar();
}
finally
{
    connection.Dispose();
}

अंत में बयानों को हमेशा फ़ंक्शन रिटर्न से पहले कॉल किया जाएगा और इसलिए कनेक्शन हमेशा बंद / निपटारा किया जाएगा।

इसलिए, आपके दूसरे उदाहरण में कोड निम्नलिखित के लिए संकलित किया जाएगा:

try
{
    try
    {
        connection.Open();

        string storedProc = "GetData";
        SqlCommand command = new SqlCommand(storedProc, connection);
        command.CommandType = CommandType.StoredProcedure;
        command.Parameters.Add(new SqlParameter("@EmployeeID", employeeID));

        return (byte[])command.ExecuteScalar();
    }
    finally
    {
        connection.Dispose();
    }
}
catch (Exception)
{
}

अपवाद अंततः कथन में पकड़ा जाएगा और कनेक्शन बंद हो जाएगा। बाहरी कैच क्लॉज द्वारा अपवाद नहीं देखा जाएगा।


1
बहुत अच्छे उदाहरण हैं आदमी, लेकिन मुझे आपकी पिछली टिप्पणी पर असहमत होना पड़ता है, अगर एक प्रयोग ब्लॉक के भीतर कोई अपवाद होता है, तो यह किसी भी बाहरी पकड़ पर समस्याओं के बिना पकड़ा जाएगा, वास्तव में मैंने इसे एक कोशिश / कैच ब्लॉक के अंदर 2 ब्लॉक का उपयोग करके लिखा था , और मेरे आश्चर्य के लिए, मुझे अपना अपवाद त्रुटि संदेश मिला जो कि ब्लॉक का उपयोग करके दूसरे से आया था।
WhySoS रहस्यमय

1

मैं दो लिखा का उपयोग कर एक के अंदर बयान ट्राई / कैच ब्लॉक और मैं देख सकता अपवाद उसी तरह पकड़ा जा रहा था अगर यह आंतरिक के भीतर रखा है का उपयोग करते हुए सिर्फ ShaneLS के रूप में बयान उदाहरण

     try
     {
       using (var con = new SqlConnection(@"Data Source=..."))
       {
         var cad = "INSERT INTO table VALUES (@r1,@r2,@r3)";

         using (var insertCommand = new SqlCommand(cad, con))
         {
           insertCommand.Parameters.AddWithValue("@r1", atxt);
           insertCommand.Parameters.AddWithValue("@r2", btxt);
           insertCommand.Parameters.AddWithValue("@r3", ctxt);
           con.Open();
           insertCommand.ExecuteNonQuery();
         }
       }
     }
     catch (Exception ex)
     {
       MessageBox.Show("Error: " + ex.Message, "UsingTest", MessageBoxButtons.OK, MessageBoxIcon.Error);
     }

कोई फर्क नहीं पड़ता कि कोशिश / पकड़ कहाँ रखी गई है, अपवाद बिना मुद्दों के पकड़ा जाएगा।

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