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