2009-05-06 6 views
5

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

class Program 
{ 
    SQLiteConnection sourceConnection; 
    SQLiteConnection destinationConnection; 

    static void Main(string[] args) 
    { 
     Program shell = new Program(); 

     // get connection strings from command line arguments 
     string sourceConnectionString = shell.getConnectionString(args); 
     string destinationConnectionString = shell.getConnectionString(args); 

     // call non-static methods that use 
     shell.setUpConnections(sourceConnectionString, destinationConnectionString); 

     shell.doDatabaseWork(); 
    } 

    private void setUpConnections(string sourceConnectionString, string destinationConnectionString) 
    { 
     sourceConnection = new SQLiteConnection(sourceConnectionString); 
     destinationConnection = new SQLiteConnection(destinationConnectionString); 
    } 

    private void doDatabaseWork() 
    { 
     // use the connections here 
    } 
} 

संपादित करें:

कुछ लोगों को समझ नहीं सकता क्यों मैं उन्हें सदस्य चर के रूप में चाहते हैं।

foreach (Row sourceRow in DBResultSet) 
{ 
    string sourceXml = sourceRow.Columns["MyColumnName"].Value; 
    string destinationXML = transformUsingXSLT(sourceXml); 
    writeToDestination(destinationXml); 
} 

देखें कि कैसे मैं इन कनेक्शन इस लूप के जीवन के लिए खुला रखने के लिए चाहते हैं: यहाँ अपने प्रयोग के मामले doDatabaseWork में जाना होगा की (एक छोटे से psuedocoded) है?

+0

आरई: संपादित करें। फिर भी ... नहीं –

उत्तर

2

मुझे लगता है कि सबसे अच्छा समाधान प्रोग्राम क्लास से मुख्य तर्क निकालना है। कार्यक्रम वर्ग प्राथमिक काम के लिए कुछ प्रकार का स्टार्टर है। और एसक्यूएलकनेक्शन के लिए रैपर प्रदान करना वास्तव में एक अच्छा विचार नहीं है, क्योंकि वे पहले ही प्रबंधित संसाधन हैं, उन्हें लपेटना अनावश्यक है। इस प्रकार मेरा समाधान इस तरह दिखता है:

class ProgramCore : IDisposable 
{ 
    internal ProgramCore(string sourceConnectionString, string destinationConnectionString) 
    { 
     setUpConnections(sourceConnectionString, destinationConnectionString); 
    } 

    internal void Execute() 
    { 
     // do whatever you want 
     doDatabaseWork(); 
     // do whatever you want 
    } 

    public void Dispose() 
    { 
     if (_sourceConnection != null) 
      _sourceConnection.Dispose(); 
     if (_destinationConnection != null) 
      _destinationConnection.Dispose(); 
    } 

    private void setUpConnections(string sourceConnectionString, string destinationConnectionString) 
    { 
     _sourceConnection = new SQLiteConnection(sourceConnectionString); 
     _destinationConnection = new SQLiteConnection(destinationConnectionString); 
    } 

    private void doDatabaseWork() 
    { 
     // use the connections here 
    } 

    private SQLiteConnection _sourceConnection; 
    private SQLiteConnection _destinationConnection; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     // get connection strings from command line arguments 
     string sourceConnectionString = GetConnectionString(args); 
     string destinationConnectionString = GetConnectionString(args); 

     using (ProgramCore core = new ProgramCore(sourceConnectionString, destinationConnectionString)) 
     { 
      core.Execute(); 
     } 
    } 

    static string GetConnectionString(string[] args) 
    { 
     // provide parsing here 
    } 
} 
+0

कनेक्शन ले लिए गए हैं। इसलिए यदि आप उन्हें 1000 बार एक बार नहीं खोलते और बंद नहीं करते हैं, तो यह आपके प्रोग्राम के प्रदर्शन को प्रभावित नहीं करेगा। लेकिन अगर आपको अक्सर कनेक्शन खोलने और बंद करने की आवश्यकता होती है, तो आपको अपने कार्यक्रम के अंदर डेटा के कैशिंग का उपयोग करना चाहिए। लेकिन यह अनुकूलन से संबंधित है, और आपको इसे अनुकूलित करने के लिए सावधानी से अपने प्रोग्राम को प्रोफ़ाइल करना चाहिए। याद रखें कि डोनाल्ड नूथ ने ऑप्टिमाइज़ेशन पर क्या कहा: "हमें छोटी क्षमता के बारे में भूल जाना चाहिए, समय के बारे में 9 7% कहें: समयपूर्व अनुकूलन सभी बुराइयों की जड़ है"। –

+0

पर्याप्त मेला, लेकिन मेरी पहली रणनीति डीबी कनेक्शन को खोलने और बंद करने के लिए थी क्योंकि मुझे उनकी आवश्यकता थी। यह लिपि के जीवन के दौरान एक क्रॉल में धीमा हो गया। मैंने प्रोफाइल नहीं किया था, लेकिन यहां तक ​​कि प्रति 1000 कनेक्शन के समूहों में लिखने के लिए समूह को भी व्यवस्थित किया गया। – danieltalsky

+0

ईमानदारी से, कोई भी आपकी रणनीति को ऊपर नहीं उठाता है, लेकिन अब तक यह मेरे प्रश्न का उत्तर देने वाला सबसे नज़दीकी है। – danieltalsky

6

आईडीस्पोज़ेबल लागू करने वाली कक्षा लिखने के बारे में कैसे।

अपने क्लास कन्स्ट्रक्टर के अंदर, आप अपने डीबी कनेक्शन को तुरंत चालू कर सकते हैं।

फिर अपने IDISposable के अंदर। विधि का प्रयोग करें, आप अपने डीबी कनेक्शन बंद करने के लिए अपना आंसू कोड लिखते हैं।

public class DBWrapper : IDisposable 
{ 
    public SqlConnection Connection1 { get; set; } 
    public SqlConnection Connection2 { get; set; } 

    public DBWrapper() 
    { 
     Connection1 = new SqlConnection(); 
     Connection1.Open(); 
     Connection2 = new SqlConnection(); 
     Connection2.Open(); 
    } 
    public void DoWork() 
    { 
     // Make your DB Calls here 
    } 

    public void Dispose() 
    { 
     if (Connection1 != null) 
     { 
      Connection1.Dispose(); 
     } 
     if (Connection2 != null) 
     { 
      Connection2.Dispose(); 
     } 
    } 
} 

और फिर, अपने कार्यक्रम वर्ग के अपने मुख्य विधि के भीतर से:

यहाँ प्रदर्शित करने के लिए मैं क्या मतलब है एक कोड नमूना है

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (DBWrapper wrapper = new DBWrapper()) 
     { 
      wrapper.DoWork(); 
     } 
    } 
} 
+0

ठीक है, लेकिन मेरे पास दो डेटाबेस कनेक्शन हैं और उन्हें एक से संसाधनों को पकड़ने, उन्हें बदलने, और दूसरे को लिखने में सक्षम होना चाहिए। मैं प्रत्येक पढ़ने और लिखने के लिए पुनः कनेक्ट नहीं करना चाहता हूं। मैं बस दोनों को खोलने के लिए एक हैंडल रखना चाहता हूं, और फिर मुझे जितनी जरूरत हो, प्रत्येक पर संचालन करने में सक्षम होना चाहिए। क्या मैं SourceWrapper.DoWork (destinationWrapper) करता हूँ? – danieltalsky

+0

उस कनेक्शन ऑब्जेक्ट पर 2 या अधिक पाठकों को खोलने का प्रयास करें और देखें कि यह इतनी अच्छी तरह से क्यों काम नहीं करेगा –

+0

मैंने 2 कनेक्शन ऑब्जेक्ट्स के साथ अधिक स्पष्ट होने के लिए अपना कोड नमूना बदल दिया है, आपको दोनों की पहुंच मिल गई है SqlConnections, आप जो कुछ भी चाहते हैं, वह कर सकते हैं, प्रत्येक पढ़ने और लिखने के लिए पुनः कनेक्ट किए बिना। असल में, आप डीबी तर्क को डीबीड्रैपर.डॉवर्क() विधि में और अपने प्रोग्राम से दूर कर रहे हैं। मुख्य विधि। –

2

स्कॉट के जवाब एक ही रास्ता यह करने के लिए है । आप अंततः कोशिश {} का उपयोग करने पर विचार कर सकते हैं?

static void Main(string[] args) 
{ 
    Program shell = new Program(); 

    // get connection strings from command line arguments 
    string sourceConnectionString = shell.getConnectionString(args); 
    string destinationConnectionString = shell.getConnectionString(args); 

    // call non-static methods that use 
    shell.setUpConnections(sourceConnectionString, destinationConnectionString); 
    try 
    { 
     shell.doDatabaseWork(); 
    } 
    finally 
    { 
     if(sourceConnection != null) 
     sourceConnection.Dispose(); 
     if(destinationConnection != null) 
     destinationConnection.Dispose(); 
    } 
} 
+2

फिर स्रोत कनेक्शन और गंतव्य कनेक्शन के लिए उपयोग करने वाले कीवर्ड का उपयोग क्यों न करें? –

+0

क्या यह काम करेगा? एक वैध कोड नमूना का उत्तर दें और दिखाएं, ब्रायन? – danieltalsky

2

व्यक्तिगत रूप से, मुझे लगता है कि आप इस सोच से अधिक कर रहे हैं और इस सूत्र में कोड नमूने बहुत जटिल imho हैं। मुझे नहीं पता कि लोग अपने प्रोग्राम क्लास पर आईडीस्पोजेबल क्यों लागू कर रहे हैं या तो जब यह निकलता है तो इसका निपटारा किया जाता है।

मैं उपयोग करने का एक कारण नहीं सोच सकता या आप उपयोग() {} कथन का उपयोग क्यों नहीं कर सकते।

आप एक कनेक्शन खोलना चाहते हैं और इसे पकड़ना चाहते हैं? क्यूं कर? सभी वास्तविक कनेक्शन .net कनेक्शन पूलिंग के दृश्यों के पीछे हैं, इसलिए नए कनेक्शन कनेक्शन ऑब्जेक्ट्स एक बड़ा सौदा नहीं है। बस उन्हें खोलने के लिए खुले और बंद करें और कनेक्शन पूलिंग दृश्यों के पीछे जो कुछ भी संभालती है।

मैंने इसे एक कक्षा में लपेटने के लिए अपना उदाहरण संपादित किया ताकि आप अपना encapsulation भी प्राप्त कर सकें।

class Program 
{ 
    static void Main(string[] args) 
    { 
     DBWorker worker = new DBWorker(); 
     worker.DoDatabaseWork(); 
    } 
} 

public class DBWorker 
{ 

    private void DoDatabaseWork() 
    { 
     using (SQLiteConnection sourceDB = new SQLiteConnection(GetConnectionString())) 
     { 
      sourceDB.Open(); 
      using (SQLiteConnection destDB = new SQLiteConnection(GetConnectionString())) 
      { 
       destDB.Open(); 
      } 
     } 
    } 

} 
+0

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

+0

मैंने यह दिखाने के लिए एक संपादन जोड़ा कि मैं उस कोड के साथ क्यों संघर्ष करूंगा। कनेक्शन पूल से – danieltalsky

0

हम्म, मुझे लगता है कि किसी ने इसे इस तरह से करने का उल्लेख नहीं किया है। आपके पास वेरिएबल्स नहीं हैं जिनका उपयोग using स्थानीय रूप से घोषित किया गया है।


class Program 
{ 
    SQLiteConnection sourceConnection; 
    SQLiteConnection destinationConnection; 

    static void Main(string[] args) 
    { 
     Program shell = new Program(); 

     // get connection strings from command line arguments 
     string sourceConnectionString = shell.getConnectionString(args); 
     string destinationConnectionString = shell.getConnectionString(args); 

     using (sourceConnection = new SQLiteConnection(sourceConnectionString)) 
     using (destinationConnection = new SQLiteConnection(destinationConnectionString)) 
     { 
      shell.doDatabaseWork(); 
     } 
    } 

    private void doDatabaseWork() 
    { 
     // use the connections here 
    } 
} 
संबंधित मुद्दे

 संबंधित मुद्दे