केवल पहली जगह में टिप्पणी करने के लिए खेद है, लेकिन मैं लगभग हर दिन एक समान टिप्पणी पोस्ट कर रहा हूं क्योंकि बहुत से लोग सोचते हैं कि एडीओ.नेट कार्यक्षमता को डीबी-क्लास (मुझे भी 10 साल पहले) में समाहित करना स्मार्ट होगा। अधिकतर वे स्थिर/साझा वस्तुओं का उपयोग करने का निर्णय लेते हैं क्योंकि यह किसी भी क्रिया के लिए एक नई वस्तु बनाने की तुलना में तेज़ लगता है।
यह न तो प्रदर्शन के मामले में और न ही विफलता-सुरक्षा के मामले में एक अच्छा विचार है।
कनेक्शन-पूल के क्षेत्र में अवैध शिकार न करें
एक अच्छा कारण है कि ADO.NET आंतरिक रूप से ADO-NET कनेक्शन-पूल में DBMS के अंतर्निहित कनेक्शन का प्रबंधन करता है:
<ब्लॉककोट>व्यवहार में, अधिकांश एप्लिकेशन कनेक्शन के लिए केवल एक या कुछ भिन्न कॉन्फ़िगरेशन का उपयोग करते हैं। इसका मतलब है कि आवेदन निष्पादन के दौरान, कई समान कनेक्शन बार-बार खोले और बंद किए जाएंगे। कनेक्शन खोलने की लागत को कम करने के लिए, ADO.NET कनेक्शन पूलिंग नामक एक अनुकूलन तकनीक का उपयोग करता है।
कनेक्शन पूलिंग नए कनेक्शनों को खोले जाने की संख्या को कम करता है। पूलर भौतिक कनेक्शन का स्वामित्व रखता है। यह प्रत्येक दिए गए कनेक्शन कॉन्फ़िगरेशन के लिए सक्रिय कनेक्शन के एक सेट को जीवित रखकर कनेक्शन का प्रबंधन करता है। जब भी कोई उपयोगकर्ता किसी कनेक्शन पर ओपन कॉल करता है, तो पूलर पूल में उपलब्ध कनेक्शन की तलाश करता है। यदि कोई पूल्ड कनेक्शन उपलब्ध है, तो यह नया कनेक्शन खोलने के बजाय इसे कॉलर को लौटा देता है। जब एप्लिकेशन कनेक्शन को बंद करता है, तो पूलर इसे बंद करने के बजाय सक्रिय कनेक्शन के पूल किए गए सेट पर वापस कर देता है। एक बार जब कनेक्शन पूल में वापस आ जाता है, तो यह अगली ओपन कॉल पर पुन:उपयोग के लिए तैयार होता है।
तो स्पष्ट रूप से कनेक्शन बनाने, खोलने या बंद करने से बचने का कोई कारण नहीं है क्योंकि वास्तव में वे बनाए, खोले और बंद नहीं किए गए हैं। कनेक्शन पूल के लिए यह "केवल" ध्वज है यह जानने के लिए कि कनेक्शन का पुन:उपयोग किया जा सकता है या नहीं। लेकिन यह एक बहुत ही महत्वपूर्ण ध्वज है, क्योंकि यदि कोई कनेक्शन "उपयोग में है" (कनेक्शन पूल मानता है), तो डीबीएमएस के लिए एक नया भौतिक कनेक्शन खुला होना चाहिए जो बहुत महंगा है।
तो आप कोई प्रदर्शन सुधार नहीं बल्कि विपरीत प्राप्त कर रहे हैं। यदि निर्दिष्ट अधिकतम पूल आकार (100 डिफ़ॉल्ट है) तक पहुंच गया है, तो आपको अपवाद भी मिलेंगे (बहुत सारे खुले कनेक्शन ...) तो यह न केवल प्रदर्शन को जबरदस्त रूप से प्रभावित करेगा बल्कि डेटा-डंपिंग-क्षेत्र (लेन-देन का उपयोग किए बिना) खराब त्रुटियों का स्रोत भी होगा।
यदि आप स्थिर कनेक्शन का भी उपयोग कर रहे हैं तो आप इस ऑब्जेक्ट तक पहुंचने का प्रयास करने वाले प्रत्येक थ्रेड के लिए लॉक बना रहे हैं। ASP.NET स्वभाव से एक मल्टीथ्रेडिंग वातावरण है। तो इन तालों के लिए एक बड़ा मौका है जो प्रदर्शन के मुद्दों को सबसे अच्छा बनाता है। वास्तव में देर-सबेर आपको कई अलग-अलग अपवाद मिलेंगे (जैसे कि आपके ExecuteReader को एक खुले और उपलब्ध कनेक्शन की आवश्यकता है )।
निष्कर्ष :
- कनेक्शन या किसी भी ADO.NET ऑब्जेक्ट का पुन:उपयोग न करें।
- उन्हें स्थिर/साझा न करें(VB.NET में)
- हमेशा बनाएं, खोलें (कनेक्शन के मामले में), उपयोग करें, बंद करें और जहां आपको उनकी आवश्यकता हो, उन्हें निपटाने (उदाहरण के लिए एक विधि में)
using-statement
का उपयोग करें निपटाने और बंद करने के लिए (कनेक्शन के मामले में) परोक्ष रूप से
यह न केवल कनेक्शन के लिए सच है (हालांकि सबसे अधिक ध्यान देने योग्य)। IDisposable
implementing को लागू करने वाली प्रत्येक वस्तु निपटाया जाना चाहिए (using-statement
द्वारा सरलतम) ), और भी अधिक System.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 [email protected]";
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;
}