2009-01-05 11 views
16

में IDbConnection या कनेक्शन स्ट्रिंग/फैक्ट्री को साझा करने के सर्वोत्तम अभ्यास। मैं सोच रहा हूं कि .NET एप्लिकेशन (ADO.NET में डेटाबेस के मुख्य कनेक्शन के संबंध में सबसे अच्छा प्रक्षेपण क्या होगा लेकिन मुझे लगता है कि अभ्यास होना चाहिए किसी भी डेटा परत के लिए)। क्या मुझे डेटाबेस कनेक्शन बनाना चाहिए और इसे अपने पूरे एप्लिकेशन में प्रसारित करना चाहिए, या कनेक्शन कनेक्शन/कारखानों को पास करना बेहतर होगा और इसकी आवश्यकता होने पर कनेक्शन एड-होक बनाना होगा।आपके नेट कोड

जैसा कि मैं समझता हूं कि परफॉर्मेंस हिट पूलिंग के साथ संकेतक नहीं है और यह मुझे टूटे हुए कनेक्शन से आसानी से पुनर्प्राप्त करने की अनुमति देता है (केवल एक नया कनेक्शन बनाया जाएगा) लेकिन फिर एक कनेक्शन ऑब्जेक्ट एक अच्छा, अपेक्षाकृत उच्च स्तरीय अमूर्तता है और प्रत्येक ऑपरेशन के लिए एक नया कनेक्शन बनाना (एसक्यूएल कमांड नहीं, लेकिन एप्लिकेशन ऑपरेशन) अतिरिक्त, डुप्लिकेट कोड उत्पन्न करता है और समय/संसाधनों (?) की बर्बादी की तरह लगता है।

आप इन 2 मामलों के बारे में क्या सोचते हैं, उनके विपक्ष/पेशेवर क्या हैं और आप अपने वास्तविक जीवन अनुप्रयोगों में किस दृष्टिकोण का उपयोग कर रहे हैं?

धन्यवाद

उत्तर

11

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

यदि प्रत्येक व्यवसाय ऑब्जेक्ट को डेटाबेस में अपना स्वयं का SQLConnection बनाना होता है, तो लेनदेन एक वितरित लेनदेन में बढ़ेगा और मैं इससे बचना चाहता था।

मुझे किसी ऑब्जेक्ट को सहेजने के लिए पैरामीटर के रूप में SQLConnection ऑब्जेक्ट को पास करना पसंद नहीं आया, इसलिए मैंने एक कनेक्शन मैनेजर बनाया जो SQLConnection ऑब्जेक्ट बनाने के लिए SQLConnection ऑब्जेक्ट बनाने, SQLConnection ऑब्जेक्ट के उपयोग को ट्रैक करने और SQLConnection ऑब्जेक्ट को डिस्कनेक्ट करने पर संभालता है बेकार।

यहाँ ConnectionManager का एक उदाहरण के रूप में कुछ कोड है:

public class ConnectionManager: IDisposable 
{ 
    private ConnectionManager instance; 

    [ThreadStatic] 
    private static object lockObject; 
    private static Object LockObject 
    { 
     get 
     { 
      if (lockObject == null) 
       lockObject = new object(); 
      return lockObject; 
     } 
    } 

    [ThreadStatic] 
    private static Dictionary<string, ConnectionManager> managers; 
    private static Dictionary<string, ConnectionManager> Managers 
    { 
     get 
     { 
      if (managers == null) 
       managers = new Dictionary<string, ConnectionManager>(); 
      return managers; 
     } 
    } 

    private SqlConnection connection = null; 
    private int referenceCount; 
    private string name; 


    public static ConnectionManager GetManager(string connectionName) 
    { 
     lock (LockObject) 
     { 
      ConnectionManager mgr; 
      if (Managers.ContainsKey(connectionName)) 
      { 
       mgr = Managers[connectionName]; 
      } 
      else 
      { 
       mgr = new ConnectionManager(connectionName); 
       Managers.Add(connectionName, mgr); 
      } 

      mgr.AddRef(); 
      return mgr; 
     } 
    } 

    private ConnectionManager(string connectionName) 
    { 
     name = connectionName; 
     connection = new SqlConnection(GetConnectionString(connectionName)); 
     connection.Open(); 
    } 

    private string GetConnectionString(string connectionName) 
    { 
     string conString = Configuration.ConnectionString; 
     return conString; 
    } 

    public SqlConnection Connection 
    { 
     get { return connection; } 
    } 

    private void AddRef() 
    { 
     referenceCount += 1; 
    } 

    private void DeRef() 
    { 
     lock (LockObject) 
     { 
      referenceCount -= 1; 
      if (referenceCount == 0) 
      { 
       connection.Dispose(); 
       Managers.Remove(name); 
      } 
     } 
    } 

#region IDisposable Members 

    public void Dispose() 
    { 
     Dispose(true); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      DeRef(); 
     } 
    } 

    ~ConnectionManager() 
    { 
     Dispose(false); 
    } 

#endregion 

} 

यहाँ कैसे मैं एक व्यवसाय वस्तु से इसका इस्तेमाल होता है:

public void Save() 
{ 
    using (ConnectionManager mrg = ConnectionManager.GetManager("SQLConnectionString") 
    { 
     using (SQLCommand cmd = new SQLCommand) 
     { 
      cmd.connection = mgr.Connection 
      // More ADO Code Here 
     } 

     _childObject.Save(); //this child object follows the same pattern with a using ConnectionManager. 
    } 
} 

मैं एक व्यवसाय वस्तु और को सहेज अपने बच्चों को एक ही कनेक्शन ऑब्जेक्ट का उपयोग करके बचाया जाता है। जब दायरे मूल माता-पिता से दूर हो जाता है, तो उपयोग कथन कनेक्शन बंद कर देता है।

यह एक पैटर्न है जिसे मैंने रॉकी लोट्का से अपने सीएसएलए ढांचे में सीखा।

कीथ

+0

धन्यवाद कीथ। मुझे वास्तव में आपका दृष्टिकोण पसंद है - कनेक्शन मैनेजर कनेक्शन और कमांड के बीच एक अच्छी परत है (यदि आप वास्तव में चाहते हैं तो आप अपने स्वयं के पूलिंग को भी कार्यान्वित कर सकते हैं)। मुझे सीएसएलए से इस अध्याय को पढ़ना होगा। –

+0

मैं उलझन में हूं कि आप प्रबंधकों के सदस्य को थ्रेडस्टैटिक क्यों चिह्नित करना चाहते हैं। जब भी गेटटर को नए थ्रेड से एक्सेस किया जाता है, तो उस थ्रेड के लिए एक नया प्रबंधक संग्रह बनाया जाएगा? – dnewcome

+0

मैं देखता हूं कि आप थ्रेड सुरक्षा दृष्टिकोण से प्रत्येक धागे के लिए अलग प्रबंधकों को क्यों चाहते हैं। आप नहीं चाहते हैं कि एसक्यूएलकनेक्शन को थ्रेड द्वारा एक्सेस किया गया हो, जो इसे बनाया गया हो। मुझे नहीं लगता कि ऐसा करना अवैध होगा, लेकिन आप वास्तव में अप्रत्याशित चीजों के लिए दरवाजा खोलते हैं। – dnewcome

1

ADO.NET एसक्यूएल सर्वर प्रदाता ही पूलिंग कनेक्शन है। आप कनेक्शन स्ट्रिंग में MinPoolSize और MaxPoolSize द्वारा पूल आकार को नियंत्रित कर सकते हैं।

1

आपको वास्तव में इस समस्या को स्वयं नहीं संभालना चाहिए, क्योंकि वहाँ अनगिनत उपकरण हैं जो आपके लिए यह कर सकते हैं।

यदि आप वास्तव में इसे स्वयं करना चाहते हैं, तो Unit of Work पैटर्न देखें जहां आप कनेक्शन/लेनदेन जीवन चक्र प्रबंधित कर सकते हैं। आप निश्चित रूप से गंदे पानी पर नेविगेट करने की कोशिश नहीं करना चाहते हैं जहां विभिन्न स्थानों पर कनेक्शन खोले/बंद हो जाते हैं।

यदि आप अपने घटकों को सीधे डीबी कनेक्शन खोलने का फैसला करते हैं तो यह संभावना है कि कनेक्शन लाइफसाइक्ल बहुत बढ़िया हो जाएगा और परिणामस्वरूप एक ही उपयोगकर्ता ऑपरेशन के लिए कई खुले/बंद कनेक्शन होंगे।

+0

बस जोड़ने के लिए ... कुछ उपकरणों में एनएचबेर्नेट, LINQ से SQL, SubSonic, और अन्य शामिल होंगे ... –

+0

धन्यवाद बेन आप बिल्कुल सही हैं कि सामान्य परिदृश्यों में सबसे अच्छा विकल्प कुछ ऑब्जेक्ट दृढ़ता ढांचे का उपयोग करना है । दुर्भाग्य से मेरी कंपनी के उत्पाद में कई "निश्चित" ऑब्जेक्ट्स नहीं हैं बल्कि यह उपयोगकर्ताओं को कस्टम टेबल (जैसे एमएस एक्सेस) बनाने की अनुमति देता है - इसलिए मैं वास्तव में ओपीएफ का उपयोग नहीं कर सकता। –

0

एक बात का अपने उदाहरण में है कि ASP.NET क्षुधा, ThreadStatic भंडारण उपयोग नहीं करना चाहिए के रूप में एक धागा फिर से इस्तेमाल किया जा सकता है, और यदि आप अपने सभी आप वस्तुओं को साफ नहीं है सावधान रहने की एक कनेक्शन लटकने के साथ खत्म हो गया।

एएसपी.NET ऐप में मैं इसके बजाय HttpContext.Items संग्रह का उपयोग करता हूं। आप आईडीस्पोज़ेबल को कार्यान्वित कर रहे हैं, लेकिन मैंने उन परिदृश्यों को देखा है जहां देव कॉल करना भूल जाते हैं या कोड को एक प्रयोग ब्लॉक में रखें।