এক্সিকিউটরিডারের জন্য একটি উন্মুক্ত এবং উপলব্ধ সংযোগ দরকার। সংযোগের বর্তমান অবস্থা সংযোগ হচ্ছে


114

অনলাইনে এসপি.এনইটি-র মাধ্যমে এমএসএসকিউএল ডাটাবেসে সংযোগ দেওয়ার চেষ্টা করার সময়, যখন দু'জন বা আরও বেশি লোক একসাথে সংযুক্ত হয় তখন আমি নিম্নলিখিতটি পাই:

এক্সিকিউটরিডারের জন্য একটি উন্মুক্ত এবং উপলব্ধ সংযোগ দরকার। সংযোগের বর্তমান অবস্থা সংযোগ হচ্ছে।

সাইটটি আমার লোকালহোস্ট সার্ভারে দুর্দান্ত কাজ করে।

এটি মোটামুটি কোড।

public Promotion retrievePromotion()
{
    int promotionID = 0;
    string promotionTitle = "";
    string promotionUrl = "";
    Promotion promotion = null;
    SqlOpenConnection();
    SqlCommand sql = SqlCommandConnection();

    sql.CommandText = "SELECT TOP 1 PromotionID, PromotionTitle, PromotionURL FROM Promotion";

    SqlDataReader dr = sql.ExecuteReader();
    while (dr.Read())
    {
        promotionID = DB2int(dr["PromotionID"]);
        promotionTitle = DB2string(dr["PromotionTitle"]);
        promotionUrl = DB2string(dr["PromotionURL"]);
        promotion = new Promotion(promotionID, promotionTitle, promotionUrl);
    }
    dr.Dispose();
    sql.Dispose();
    CloseConnection();
    return promotion;
}

আমি কী জানতে পারি যে কী ভুল হয়েছে এবং আমি কীভাবে এটি ঠিক করব?

সম্পাদনা: ভুলে যাবেন না, আমার সংযোগের স্ট্রিং এবং সংযোগ দুটি স্থির ic আমি বিশ্বাস করি এটিই কারণ। দয়া করে উপদেশ দাও.

public static string conString = ConfigurationManager.ConnectionStrings["dbConnection"].ConnectionString;
public static SqlConnection conn = null;

24
আপনি যেমন লক বা ব্যতিক্রম (অনেক বেশি উন্মুক্ত সংযোগ ইত্যাদি) তৈরি করছেন সেহেতু এএসপি.এনইটির মতো মাল্টিথ্রেডিং-পরিবেশে ভাগ করা / স্থিতিশীল সংযোগগুলি ব্যবহার করবেন না। আপনার ডিবি-ক্লাসটি আবর্জনায় ফেলে দিন এবং আপনার যেখানে প্রয়োজন অ্যাডো.এন.টি অবজেক্ট তৈরি করতে, খুলতে, ব্যবহার করতে, বন্ধ করতে, নিষ্পত্তি করতে পারেন। পাশাপাশি ব্যবহার-বিবৃতিটি দেখুন।
টিম শেমলেটার

2
আপনি কি আমাকে SqlOpenConnication () এবং sql.ExecuteReader () সম্পর্কে বিশদ দিতে পারেন; ফাংশন? ..
অঙ্কিত রাজপুত

বেসরকারী শূন্যস্থান SqlOpenConnication () {try {conn = new SQLConnection (); conn.ConnectionString = কনস্ট্রিং; conn.Open (); } ধরা (SqlException প্রাক্তন) {নিক্ষেপ প্রাক্তন; }}
গুও হংক লিম

@ গুওহংলিম: আমি উল্লেখ করতে ভুলে গেছি যে কোনও স্থিতিশীল কোনওভাবেই ডিফল্টরূপে ক্যাশেডconString হওয়ার কারণে (বর্তমান অ্যাপ্লিকেশনের প্রতিটি কনফিগারেশন মান হিসাবে) পারফরম্যান্সের ক্ষেত্রে কিছু যোগ করে না ।
টিম শ্মেলেটার

... এবং কেবল এটি একটি পরিচিত-অজানা হিসাবে তৈরি করা: আপনার ডাটাবেস লেনদেনের পরিচালনা / ইউনিট-অফ-ওয়ার্কটি সঠিকভাবে পাওয়া নিশ্চিত করে পাঠকের পক্ষে অনুশীলন হিসাবে রেখে দেওয়া হয়েছে।
mwardm

উত্তর:


226

প্রথম স্থানে শুধুমাত্র মন্তব্য করার জন্য দুঃখিত, তবে আমি প্রায় প্রতিদিন একই ধরণের মন্তব্য পোস্ট করছি যেহেতু অনেক লোক মনে করে যে ডিবি-ক্লাসে ADO.NET কার্যকারিতা আবদ্ধ করা স্মার্ট হবে (আমারও 10 বছর আগে)। বেশিরভাগ ক্ষেত্রে তারা স্থির / ভাগ করা অবজেক্টগুলি ব্যবহার করার সিদ্ধান্ত নেয় যেহেতু কোনও ক্রিয়াকলাপের জন্য কোনও নতুন অবজেক্ট তৈরি করা তার চেয়ে দ্রুত বলে মনে হয়।

এটি পারফরম্যান্সের ক্ষেত্রে বা ব্যর্থ-সুরক্ষার দিক থেকে ভাল ধারণা নয়।

সংযোগ-পুলের অঞ্চলে পোচ করবেন না

ADO.NET অভ্যন্তরীণভাবে ADO-NET সংযোগ-পুলে DBMS- র অন্তর্নিহিত সংযোগগুলি পরিচালনা করার একটি ভাল কারণ রয়েছে :

অনুশীলনে, বেশিরভাগ অ্যাপ্লিকেশন সংযোগগুলির জন্য কেবল একটি বা কয়েকটি আলাদা কনফিগারেশন ব্যবহার করে। এর অর্থ হ'ল অ্যাপ্লিকেশন কার্যকর করার সময়, অনেকগুলি অভিন্ন সংযোগ বারবার খোলা এবং বন্ধ করা হবে। সংযোগ খোলার ব্যয়কে হ্রাস করতে, ADO.NET সংযোগ পুলিং নামে একটি অপ্টিমাইজেশন কৌশল ব্যবহার করে।

সংযোগ পুলিং নতুন সংযোগগুলি খোলার পরিমাণটি হ্রাস করে। পুলার দৈহিক সংযোগের মালিকানা বজায় রাখে। এটি প্রতিটি প্রদত্ত সংযোগ কনফিগারেশনের জন্য সক্রিয় সংযোগের সেটকে জীবিত রেখে সংযোগ পরিচালনা করে। যখনই কোনও ব্যবহারকারী কোনও সংযোগে ওপেন কল করে, পুলারটি পুলটিতে একটি উপলব্ধ সংযোগের সন্ধান করে। যদি কোনও পুলযুক্ত সংযোগ উপলব্ধ থাকে তবে এটি নতুন সংযোগ খোলার পরিবর্তে এটি কলারের কাছে ফেরত দেয়। অ্যাপ্লিকেশনটি যখন সংযোগে ক্লোজকে কল করে, পুলার এটিকে বন্ধ না করে সক্রিয় সংযোগগুলির পুলযুক্ত সেটটিতে ফেরত দেয়। একবার সংযোগটি পুলটিতে ফিরে আসার পরে এটি পরবর্তী ওপেন কলে পুনরায় ব্যবহারের জন্য প্রস্তুত।

সুতরাং স্পষ্টতই সংযোগ তৈরি করা, খোলার বা বন্ধ হওয়া এড়াতে হবে না কারণ বাস্তবে সেগুলি তৈরি করা, খোলা এবং বন্ধ করা হয়নি। সংযোগ পুলের জন্য এটি "কেবল" একটি পতাকা যা কখন সংযোগটি পুনরায় ব্যবহার করা যায় বা না তা জানতে। তবে এটি একটি অত্যন্ত গুরুত্বপূর্ণ পতাকা, কারণ যদি কোনও সংযোগটি "ব্যবহারে" হয় (সংযোগ পুলটি ধরে নেওয়া হয়) তবে একটি নতুন শারীরিক সংযোগ অবশ্যই ডিবিএমএসের জন্য খুব ব্যয়বহুল হতে হবে।

সুতরাং আপনি কোনও কার্যকারিতা উন্নতি করতে পারছেন তবে বিপরীত। যদি সর্বাধিক পুলের আকার নির্দিষ্ট করা হয় (100 টি ডিফল্ট হয়) তবে আপনি ব্যতিক্রম পেতে পারেন (অনেকগুলি মুক্ত সংযোগ ...) ... সুতরাং এটি কেবল পারফরম্যান্সকে মারাত্মকভাবে প্রভাবিত করবে না তবে এটি একটি দুষ্ট ত্রুটির জন্য এবং (লেনদেন ব্যবহার না করে) ডেটা-ডাম্পিং-এরিয়ার জন্য উত্স হয়ে উঠবে।

এমনকি যদি আপনি স্থিতিশীল সংযোগগুলি ব্যবহার করে থাকেন তবে আপনি এই বিষয়টিকে অ্যাক্সেস করার চেষ্টা করে প্রতিটি থ্রেডের জন্য একটি লক তৈরি করছেন। এএসপি.এনইটি প্রকৃতি অনুসারে একটি বহুগঠনের পরিবেশ। সুতরাং এই লকগুলির জন্য দুর্দান্ত সুযোগ রয়েছে যা সর্বোত্তমভাবে পারফরম্যান্স সমস্যার কারণ হয়। প্রকৃতপক্ষে খুব শীঘ্রই আপনি অনেকগুলি ব্যতিক্রম পাবেন (যেমন আপনার এক্সিকিউটিআরডারের জন্য একটি উন্মুক্ত এবং উপলভ্য সংযোগ প্রয়োজন )।

উপসংহার :

  • সংযোগ বা কোনও ADO.NET বস্তু একেবারে পুনরায় ব্যবহার করবেন না।
  • এগুলিকে স্থিত / ভাগ করে নেবেন না (VB.NET এ)
  • সর্বদা তৈরি করুন, খুলুন (সংযোগের ক্ষেত্রে) আপনার যেখানে যেখানে প্রয়োজন সেখানে ব্যবহার করুন, বন্ধ করুন এবং নিষ্পত্তি করুন (কোনও পদ্ধতিতে ফি)
  • ব্যবহার using-statementমীমাংসা করা এবং বন্ধ (সংযোগ ক্ষেত্রে) implicitely

এটি কেবল সংযোগগুলির জন্যই নয় (যদিও সবচেয়ে উল্লেখযোগ্য)। প্রতিটি অবজেক্ট বাস্তবায়ন করার জন্য নাম তালিকাতে আরও IDisposableসহজ সমাধান করা উচিত ।using-statementSystem.Data.SqlClient

উপরের সমস্তগুলি একটি কাস্টম ডিবি-শ্রেণির বিরুদ্ধে কথা বলে যা সমস্ত বস্তুকে আবদ্ধ করে এবং পুনরায় ব্যবহার করে। এ কারণেই আমি এটিকে আবর্জনাতে মন্তব্য করেছি। এটি কেবল একটি সমস্যার উত্স।


সম্পাদনা করুন : এখানে আপনার- retrievePromotionআদর্শের একটি সম্ভাব্য বাস্তবায়ন :

public Promotion retrievePromotion(int promotionID)
{
    Promotion promo = null;
    var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["MainConnStr"].ConnectionString;
    using (SqlConnection connection = new SqlConnection(connectionString))
    {
        var queryString = "SELECT PromotionID, PromotionTitle, PromotionURL FROM Promotion WHERE PromotionID=@PromotionID";
        using (var da = new SqlDataAdapter(queryString, connection))
        {
            // you could also use a SqlDataReader instead
            // note that a DataTable does not need to be disposed since it does not implement IDisposable
            var tblPromotion = new DataTable();
            // avoid SQL-Injection
            da.SelectCommand.Parameters.Add("@PromotionID", SqlDbType.Int);
            da.SelectCommand.Parameters["@PromotionID"].Value = promotionID;
            try
            {
                connection.Open(); // not necessarily needed in this case because DataAdapter.Fill does it otherwise 
                da.Fill(tblPromotion);
                if (tblPromotion.Rows.Count != 0)
                {
                    var promoRow = tblPromotion.Rows[0];
                    promo = new Promotion()
                    {
                        promotionID    = promotionID,
                        promotionTitle = promoRow.Field<String>("PromotionTitle"),
                        promotionUrl   = promoRow.Field<String>("PromotionURL")
                    };
                }
            }
            catch (Exception ex)
            {
                // log this exception or throw it up the StackTrace
                // we do not need a finally-block to close the connection since it will be closed implicitely in an using-statement
                throw;
            }
        }
    }
    return promo;
}

এটি সংযোগের কাজের প্যারাডিজমা দেওয়ার ক্ষেত্রে সত্যই কার্যকর। এই ব্যাখ্যার জন্য ধন্যবাদ।
অ্যামিনভিনসেন্ট

ভাল লেখা, অনেক লোক দুর্ঘটনাক্রমে এমন কিছু আবিষ্কারের জন্য একটি ব্যাখ্যা এবং আমি আশা করি আরও বেশি লোক এটি জানত। (+1)
অ্যান্ড্রু হিল

1
আপনাকে ধন্যবাদ স্যার, আমি মনে করি যে এটি এই বিষয়টির সেরা ব্যাখ্যা যা আমি কখনই পড়েছি, এমন একটি বিষয় যা অত্যন্ত গুরুত্বপূর্ণ এবং এটি অনেক নবজাতকের ভুল। আপনার চমৎকার লেখার দক্ষতার জন্য আমি অবশ্যই আপনাকে ধন্যবাদ জানাতে চাই।
স্যাসিনোসফট

@ টিম শেমলেটার কীভাবে আমি আমার থিমগুলিকে বিভিন্ন থ্রেডে চালিত করতে পারি আপনার প্রস্তাবিত পদ্ধতির সাহায্যে প্রতিশ্রুতিবদ্ধ / ঘূর্ণায়মান একক লেনদেনকে?
গাইকো

1

কিছুদিন আগে আমি এই ত্রুটিটি ধরলাম।

আমার ক্ষেত্রে এটি ছিল কারণ আমি একটি সিঙ্গেলনে লেনদেন ব্যবহার করছিলাম।

.নিট উপরে বর্ণিত হিসাবে সিঙ্গলটনের সাথে ভাল কাজ করে না।

আমার সমাধানটি হ'ল:

public class DbHelper : DbHelperCore
{
    public DbHelper()
    {
        Connection = null;
        Transaction = null;
    }

    public static DbHelper instance
    {
        get
        {
            if (HttpContext.Current is null)
                return new DbHelper();
            else if (HttpContext.Current.Items["dbh"] == null)
                HttpContext.Current.Items["dbh"] = new DbHelper();

            return (DbHelper)HttpContext.Current.Items["dbh"];
        }
    }

    public override void BeginTransaction()
    {
        Connection = new SqlConnection(Entity.Connection.getCon);
        if (Connection.State == System.Data.ConnectionState.Closed)
            Connection.Open();
        Transaction = Connection.BeginTransaction();
    }
}

আমি আমার উদাহরণের জন্য এইচটিটিপি কনটেক্সট.কন্টেনার.আইটেম ব্যবহার করেছি। এই ক্লাসটি ডিবিহেল্পার এবং ডিবিহেল্প্পোর আমার নিজস্ব ক্লাস

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