একটি "ব্যবহার" ব্লকটিতে কি কোনও এসএলএল সংযোগটি প্রত্যাবর্তন বা ব্যতিক্রম বন্ধ হয়?


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
@ ট্রুইউইল - আমি সম্মত কাঠামোর জন্য আমি কোডটি কিছুটা সরিয়ে নিয়েছি।
ডেভিড

10
প্রশ্ন: ইউজিং স্টেটমেন্টটি ব্যবহার করার সময় আমার কি কোনও সংযোগও খুলতে হবে?
Fandango68

3
এছাড়াও আপনি লেনদেনের ব্যবহার করছেন, না থাকার try catchমধ্যে usingআপনি স্পষ্টভাবে করতে পারেন .Commitবা .Rollbackলেনদেন catch। এটি উভয়ই পাঠযোগ্য এবং সুস্পষ্ট, এবং যদি ব্যতিক্রমের ধরণটি বিবেচনা করে তা বোধ করে তবে আপনাকে প্রতিশ্রুতিবদ্ধ হওয়ার অনুমতি দেয়। ( conn.Closeযদি প্রতিশ্রুতিবদ্ধ না হয় তবে লেনদেনগুলি স্পষ্টতই পিছনে ফিরে আসে ))
ক্রিস

8
@ ফার্নান্দো 68 হ্যাঁ, আপনার এখনও Openসংযোগ রয়েছে। usingকেবলমাত্র গ্যারান্টি দেয় যে অবজেক্টের Disposeপদ্ধতিটি বলা হয়।
juharr

ব্লক ব্যবহার করে আমার ভিতরে ফিরতি এক্সিকিউটিস্কেলার রয়েছে। এবং আমি যখন দ্বিতীয়বার পদ্ধতিটি চালাচ্ছি তখন এটি খুব দ্রুত, যেমন সংযোগটি খোলা ছিল। দ্বিতীয়বার এত তাড়াতাড়ি কেন?
ইতিবাচক দৃষ্টিকোণ

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 এ কাস্ট ঠিক করা


এটি ঠিক এটি নয়, তবে এটি যথেষ্ট কাছে। সঠিক পার্থক্য গুরুত্বপূর্ণ নয়।
ব্রায়ান

@ ব্রায়ান তা পান নি, আপনি কি দয়া করে সঠিক পার্থক্যটি উল্লেখ করতে পারেন, আমাদের আরও
ঝুঁকতে

বাহ, এটি একটি দীর্ঘ সময় আগে একটি মন্তব্য ছিল :) মনে হচ্ছে আমি মন্তব্য করার পরের দিন একটি সম্পাদনা ছিল। আমি মনে করি যে পার্থক্যটি আমি ভাবছিলাম।
ব্রায়ান

@ ব্রায়ান হ্যাঁ, আমি আপনার মন্তব্যের পরে সামঞ্জস্য করেছি।
রায়ান পেডারসেন

17

এখানে আমার টেম্পলেট। আপনার এসকিউএল সার্ভার থেকে ডেটা নির্বাচন করার জন্য প্রয়োজনীয় সমস্ত কিছুই। সংযোগ বন্ধ এবং নিষ্পত্তি হয় এবং সংযোগ এবং কার্যকর করার ক্ষেত্রে ত্রুটি ধরা পড়ে।

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 *
নিকজির পরামর্শ অনুসারে; যদি অনেকগুলি ধনুর্বন্ধনী আপনাকে বিরক্ত করে থাকে তবে এই জাতীয় বিন্যাস করুন ...

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
আপনি কি জানতেন আপনি অতিরিক্ত ব্রেস ছাড়া স্টেটমেন্ট ব্যবহার করে স্ট্যাক করতে পারেন? শেষ
বন্ধনীটি

জী জনাব. ধন্যবাদ. আমি সচেতন তবে আমার কোডটি চাইছিল যে খুব বেশি অন্যান্য শর্ট কাট ব্যবহার না করে ঠিক কী ঘটছে তা দেখাতে চাই। শেষ পাঠকদের যদিও যোগ করার জন্য ভাল নোট।
শ্যানলস

কেন আপনি conn.Close();শেষে ব্যবহার করবেন ? usingবিবৃতি নিষ্পত্তি করার মাধ্যমে আপনার পক্ষে তা করে না?
ফ্রেড্রিক গাউস

আমি বিশ্বাস করি এটি এখন ঘটে (নেট। 3.5।) নেট নেট ২.০ দিয়ে প্রথম দিকে এটি আমার কাছে অস্পষ্ট ছিল তাই আমি এটি পরীক্ষা করে বন্ধ করার অভ্যাসটি করেছিলাম।
শেনএলএস

1
"23 এর পরিবর্তে 1 লাইনটির অর্থ আমি একজন ভাল প্রোগ্রামার, তাই না?" আমি আপনাকে পছন্দ করি :
ফিলিপ মুলার

5

আপনি যখন ব্যবহারের সুযোগ ছেড়ে যাবেন তখন নিষ্পত্তি কেবলমাত্র কল হয়ে যায়। "ব্যবহার" করার উদ্দেশ্যটি হ'ল বিকাশকারীদের যাতে নিশ্চিত হওয়া যায় যে সম্পদগুলি নিষ্পত্তি হয় তার একটি গ্যারান্টিযুক্ত উপায় give

এমএসডিএন থেকে :

ব্যবহারের বিবৃতিটি শেষ হয়ে গেলে বা কোনও ব্যতিক্রম ছুঁড়ে দেওয়া হয় এবং নিয়ন্ত্রণ বিবৃতিটি শেষ হওয়ার আগে বিবৃতিটিকে অবরুদ্ধ করে রাখলে একটি ব্যবহারের বিবৃতিটি প্রস্থান করা যেতে পারে।


5

Usingবরাদ্দ করা অবজেক্টের চারপাশে একটি চেষ্টা / অবশেষে উত্পন্ন করে এবং Dispose()আপনাকে কল করে ।

এটি আপনাকে ম্যানুয়ালি চেষ্টা / শেষ অবধি ব্লক এবং কলিংয়ের ঝামেলা বাঁচায় Dispose()


3

আপনার প্রথম উদাহরণে, সি # সংকলক আসলে ব্যবহারের বিবৃতিটি নিম্নলিখিতটিতে অনুবাদ করবে:

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 লিখে এটি পরীক্ষা করেছি , এবং আমার অবাক করে দিয়েছি যে আমার ব্যতিক্রম ত্রুটি বার্তাটি দেখানো হয়েছে যা ব্লক ব্যবহার করে ভিতরের দ্বিতীয়টি থেকে এসেছিল।
হোয়সসরিয়াস

1

আমি চেষ্টা / ক্যাচ ব্লকের ভিতরে দুটি বিবৃতি ব্যবহার করে লিখেছিলাম এবং ব্যতিক্রমগুলি শ্যানএলএস উদাহরণ হিসাবে যেমন অভ্যন্তরীণ বিবরণটি ব্যবহার করে অভ্যন্তরের অভ্যন্তরে রাখা হয় তবে একইভাবে ধরা পড়তে পারলাম ।

     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);
     }

চেষ্টা / ধরা যেখানেই থাকুক না কেন , ব্যতিক্রম সমস্যা ছাড়াই ধরা পড়বে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.