2008-10-30 18 views
21

सोच रहा था कि क्या इसे डेटाबेस कनेक्शन ऑब्जेक्ट को पास करने के लिए अनुशंसित किया गया है (अन्य मॉड्यूल में) या विधि (अन्य मॉड्यूल में) इसे स्थापित करने का ख्याल रखने दें। मैं विधि को इसे सेट करने से पहले कनेक्शन की स्थिति की जांच करने की अनुमति देने की ओर झुका रहा हूं, और केवल कॉलर को कॉलिंग विधि में किसी भी आवश्यक डेटा को पास करने के लिए कनेक्शन सेट अप करने की आवश्यकता होगी।विधियों को डीबी कनेक्शन ऑब्जेक्ट पास करने के लिए

उत्तर

13

व्यक्तिगत तौर पर मैं कसकर उपयोग करना चाहेंगे (अर्थ नहींं यह आप अन्य डेटाबेस के साथ काम करने की योजना बना रहे एक SqlConnection पारित) स्कॉप्ड कनेक्शन; उन्हें देर से खोलें, उनका उपयोग करें, और उन्हें बंद करें ("उपयोग" ब्लॉक में, सभी स्थानीय विधि के भीतर)। कनेक्शन पूलिंग ज्यादातर मामलों में कनेक्शन का पुन: उपयोग करने के साथ सौदा करेगी, इसलिए इस दृष्टिकोण में कोई वास्तविक ओवरहेड नहीं है।

कनेक्शन पास करने में मुख्य लाभ का उपयोग किया गया ताकि आप लेनदेन को पार कर सकें; हालांकि, TransactionScope विधियों के बीच लेनदेन साझा करने का एक आसान तरीका है।

चूंकि कक्षाएं कार्यान्वयन विशिष्ट हैं, इसलिए मैं प्रत्येक को अपना मूल लेनदेन खोलने के लिए लिखूंगा। अन्यथा, आप configo फ़ाइल (प्रदाता नाम) से उपयुक्त प्रकार बनाने के लिए ado.net फैक्टरी विधियों का उपयोग कर सकते हैं।

+4

में प्रत्येक विधि पर दो अतिरिक्त पैरा की आवश्यकता के बिना हल करता है यदि आप विभिन्न कनेक्शनों का उपयोग करने वाले तरीकों के बीच लेनदेन साझा करने के लिए ट्रांज़ेक्शनस्कोप का उपयोग करते हैं, तो लेनदेन एक वितरित लेनदेन बन जाता है संबंधित ओवरहेड। इसलिए स्कोप को कसकर रखते हुए, तरीकों के बीच एक कनेक्शन (और इसके लेनदेन) को पार करना अक्सर बेहतर होता है। – Joe

+0

एक और कारण है कि मैं इस सामान के लिए टीएलएस का उपयोग करना पसंद करता हूं –

+0

इस तरह हम आमतौर पर ऐसा करते हैं, और जिस तरह से मैं इसे पसंद करता हूं। – CSharpAtl

1

मैं व्यक्तिगत रूप से जितना संभव हो सके अपने डेटा एक्सेस को केंद्रीकृत करने के लिए काम करता हूं, हालांकि, यदि संभव नहीं है तो मैं हमेशा अन्य कक्षाओं में एक नया कनेक्शन खोलता हूं, क्योंकि मुझे लगता है कि कई अन्य चीजें हैं जो रास्ते में हो सकती हैं वास्तविक कनेक्शन ऑब्जेक्ट पास करना।

0

मैं web.config

<configuration> 
    <connectionStrings> 
     <add name="conn1" providerName="System.Data.SqlClient" connectionString="string here" /> 
     <add name="conn2" providerName="System.Data.SqlClient" connectionString="string here" /> 
    </connectionStrings> 
</configuration> 

का प्रयोग करेंगे तो फिर तुम आवेदन

+0

लेकिन मैं नहीं चाहता कि प्रत्येक टुकड़े को कॉन्फ़िगरेशन से प्राप्त करना पड़े, 1 वर्ग है जो कनेक्शन प्रबंधित करता है – CSharpAtl

+0

क्या एन्क्रिप्शन के बिना कॉन्फ़िगरेशन फ़ाइल में कनेक्शन स्ट्रिंग रखना सुरक्षित है? –

1

कनेक्शन की स्थापना में कहीं से भी यह संदर्भित कर सकते हैं संभावित महंगा है और संभवतः एक राउंड ट्रिप कहते हैं। तो, फिर, संभावित रूप से, बेहतर डिजाइन कनेक्शन ऑब्जेक्ट को पास करना है।

मैं संभवतः कहते हैं, क्योंकि आप किसी Microsoft ADO अनुप्रयोग रहे हैं, तो आप शायद एक कनेक्शन पूल ....

+1

आम तौर पर, पूलिंग बहुत खुशी से ... और न सिर्फ वेब के लिए। –

+0

ठीक है, मैंने "वेब" शब्द हटा दिया –

8

स्वचालित परीक्षण प्रयोजनों के लिए उपयोग कर रहे हैं, यह आमतौर पर उस में पारित करने के लिए आसान है। यह dependency injection कहा जाता है।

जब आपको परीक्षण लिखने की आवश्यकता होती है, तो आप एक नकली डेटाबेस कनेक्शन ऑब्जेक्ट बना सकते हैं और वास्तविक के बजाय इसे पास कर सकते हैं। इस तरह, आपके स्वचालित परीक्षण वास्तविक डेटाबेस पर भरोसा नहीं करेंगे जिन्हें हर बार डेटा के साथ दोहराने की आवश्यकता होती है।

+1

थ्रेड स्थानीय भंडारण इसे –

1

यहां इस समस्या में थोड़ा और अंतर्दृष्टि है। मेरे पास एक कक्षा है जो डीबी कनेक्शन प्रबंधित करती है, और इसमें 2 कक्षाएं हैं जो इंटरफ़ेस को कार्यान्वित करती हैं। कक्षाओं में से एक एसक्यूएल के लिए है और दूसरा ओलाप है। प्रबंधक वह है जो जानता है कि किस कनेक्शन का उपयोग करना है, इसलिए यह प्रकार के सटीक कनेक्शन को पारित कर सकता है, या प्रकार अपना कनेक्शन बना सकता है।

1

आप किसी भी समस्या के बिना कनेक्शन ऑब्जेक्ट्स पास कर सकते हैं (उदाहरण के लिए माइक्रोसॉफ्ट एंटरप्राइज़ लाइब्रेरी एक स्थिर कनेक्शन कॉल को कनेक्शन में गुजरने की अनुमति देता है) या आप इसे अपने डिज़ाइन तक बाहरी रूप से प्रबंधित कर सकते हैं, प्रत्यक्ष तकनीकी ट्रेडऑफ नहीं हैं।

पोर्टेबिलिटी एक विशिष्ट कनेक्शन पारित करने के लिए नहीं करने के लिए सावधान रहें अपने समाधान अन्य डेटाबेस में पोर्ट किया जाएगा यदि

9

व्यक्तिगत रूप से, मुझे सेटडाटा और गेटडाटा का उपयोग करके Thread Local Storage के शीर्ष पर अपने वर्तमान खुले कनेक्शन और लेनदेन के ढेर को संग्रहित करना पसंद है।मैं एक वर्ग को परिभाषित करता हूं जो डेटाबेस से मेरे कनेक्शन प्रबंधित करता है और इसे निपटान पैटर्न का उपयोग करने की अनुमति देता है। यह मुझे कनेक्शन और लेन-देन को पारित करने की आवश्यकता को बचाता है, जो कुछ ऐसा है जो मुझे लगता है कि क्लटर और कोड को जटिल करता है।

मैं के खिलाफ दृढ़ता से अनुशंसा करता हूं कि जब भी उन्हें डेटा की आवश्यकता हो, कनेक्शन को खोलने के तरीकों तक इसे छोड़ दें। यह वास्तव में एक खराब स्थिति की ओर ले जाएगा जहां पूरे आवेदन में लेनदेन का प्रबंधन करना मुश्किल है और बहुत से कनेक्शन खोले और बंद हो गए हैं (मुझे कनेक्शन पूलिंग के बारे में पता है, पूल से कनेक्शन देखने के लिए अभी भी महंगा है

class DatabaseContext : IDisposable { 

    List<DatabaseContext> currentContexts; 
    SqlConnection connection; 
    bool first = false; 

    DatabaseContext (List<DatabaseContext> contexts) 
    { 
     currentContexts = contexts; 
     if (contexts.Count == 0) 
     { 
      connection = new SqlConnection(); // fill in info 
      connection.Open(); 
      first = true; 
     } 
     else 
     { 
      connection = contexts.First().connection; 
     } 

     contexts.Add(this); 
    } 

    static List<DatabaseContext> DatabaseContexts { 
     get 
     { 
      var contexts = CallContext.GetData("contexts") as List<DatabaseContext>; 
      if (contexts == null) 
      { 
       contexts = new List<DatabaseContext>(); 
       CallContext.SetData("contexts", contexts); 
      } 
      return contexts; 
     } 
    } 

    public static DatabaseContext GetOpenConnection() 
    { 
     return new DatabaseContext(DatabaseContexts); 
    } 


    public SqlCommand CreateCommand(string sql) 
    { 
     var cmd = new SqlCommand(sql); 
     cmd.Connection = connection; 
     return cmd; 
    } 

    public void Dispose() 
    { 
     if (first) 
     { 
      connection.Close(); 
     } 
     currentContexts.Remove(this); 
    } 
} 



void Test() 
{ 
    // connection is opened here 
    using (var ctx = DatabaseContext.GetOpenConnection()) 
    { 
     using (var cmd = ctx.CreateCommand("select 1")) 
     { 
      cmd.ExecuteNonQuery(); 
     } 

     Test2(); 
    } 
    // closed after dispose 
} 

void Test2() 
{ 
    // reuse existing connection 
    using (var ctx = DatabaseContext.GetOpenConnection()) 
    { 
     using (var cmd = ctx.CreateCommand("select 2")) 
     { 
      cmd.ExecuteNonQuery(); 
     } 
    } 
    // leaves connection open 
} 
+0

जिज्ञासा से, टेस्ट में खोले गए कनेक्शन को बंद करने से टेस्ट 2 में निपटान() कॉल को क्या रोकता है? मुझे लगता है कि डेटाबेस कॉन्टेक्स्ट को कनेक्शन के लिए पूछे गए ग्राहकों की संख्या का ट्रैक रखना होगा और केवल 1 अनुरोध खुला होने पर ही कनेक्शन को बंद करने का निपटान करने की अनुमति होगी। इस प्रकार यह होगा कि निपटान डेटाबेस कॉन्टेक्स्ट के अंदर ग्राहकों की संख्या को भी कम करेगा। अनुचित युग्मन के लिए एक अवसर की तरह लगता है (शायद तय किया जा सकता है)। इसके अलावा, क्या होता है जब आपको धागे में एक ट्रैन साझा करने की आवश्यकता होती है? – xero

+0

@xero, धागे भर में ट्रैन एक काफी दुर्लभ स्थिति है, इसलिए आप इसे मैन्युअल रूप से संभालते हैं।यह खेलने के लिए एक काफी खतरनाक खेल है। जब आप कोई संदर्भ बनाते हैं तो यह जानता है कि कनेक्शन कनेक्शन है या नहीं और फिर उचित तरीके से कार्यवाही का निपटान करें –

1

मैं सुझाव है कि आप कनेक्शन वस्तु और उसके राज्य (खुला के बीच भेद, बंद): एक वस्तु)

तो मैं इन पंक्तियों (पूरी तरह अपरीक्षित साथ कुछ होने अंत) का पुन: उपयोग करने के लिए।

आपके पास एक ही विधि (या संपत्ति) हो सकती है जो web.config से कनेक्शन स्ट्रिंग को पढ़ती है। कनेक्शन स्ट्रिंग के उसी संस्करण का उपयोग हर बार सुनिश्चित करता है कि आपको कनेक्शन पूलिंग से लाभ होगा।

उस विधि को कॉल करें जब आपको कनेक्शन खोलने की आवश्यकता हो। आखिरी पल में, सभी SqlCommand गुणों को स्थापित करने के बाद, कनेक्शन खोलें, इसका उपयोग करें, और फिर इसे बंद करें। सी # में, यह सुनिश्चित करने के लिए कि कनेक्शन बंद है, आप उपयोग कथन का उपयोग कर सकते हैं। यदि नहीं, तो अंत में ब्लॉक में कनेक्शन बंद करना सुनिश्चित करें।