2010-04-02 25 views
9

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

मैं इसे की मानसिकता में इस तरह से किया था "खुला देर हो गई, करीब जल्दी" ... लेकिन क्या अगर मैं एक एकल लेनदेन में डेटा प्रस्तुत करने के लिए अन्य बीओ कॉल करने के लिए की जरूरत है? क्या खोलने और बंद करने के कनेक्शन के साथ-साथ लेनदेन के साथ काम करने का एक बेहतर तरीका है?

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

उत्तर

5

एक दिया व्यापार वस्तु के लेनदेन में विभिन्न तरीकों पर अमल करने की जरूरत है, का प्रयोग कर एक TransactionScope तो जैसे:

using (var transactionScope = new TransactionScope()) 
{ 
    this.Save(); 
    childObjA.Save(); 
    childObjB.Save(); 
    childObjC.Save(); 
    childObjD.Save(); 

    transactionScope.Complete(); 
} 

वस्तुओं में से किसी एक अपवाद फेंकता है, यह लेन-देन रोलबैक होगा।

अधिक के लिए the MSDN reference page for TransactionScope देखें।

+3

हालांकि ओपी के वर्तमान डिज़ाइन के साथ 'ट्रांज़ेक्शनस्कोप' * कक्षा का उपयोग करने के लिए कक्षा है, इसके परिणामस्वरूप एमएसडीटीसी अक्षम या लॉक हो जाने पर इसका परिणाम एक वितरित लेनदेन या संभवतः एक अपवाद होगा। यह * संभव * वांछित परिणाम नहीं है। – Aaronaught

+1

@ एरोशॉट, एसक्यूएल सर्वर 2008 और .NET 3.5 लेनदेन के साथ एक वितरित लेनदेन (वर्तमान डिजाइन के लिए) को पदोन्नत नहीं किया जाएगा। –

+2

@Tuzo: सच है, SQL सर्वर 2008 के साथ आप एकाधिक कनेक्शन समस्या को धोखा देने में सक्षम हैं ** IF ** सभी कनेक्शन एक ही डेटाबेस ** और ** एक ही समय में केवल एक ही खुला है। यह अभी भी एक सुंदर संदिग्ध अभ्यास है, खासकर जब वैकल्पिक डिजाइन को किसी भी तरह से बनाना/बनाए रखना आसान है। – Aaronaught

2

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

4

जब उच्च-स्तरीय अवशोषण निम्न-स्तर के अबास्ट्रक्शंस (जैसे डेटा कनेक्शन के आधार पर व्यवसाय तर्क वर्ग) पर निर्भर करता है, तो यह कन्स्ट्रक्टर के माध्यम से निम्न-स्तरीय अवशेषों को आपूर्ति करना आम है। तकनीक कहा जाता है निर्माता इंजेक्शन:

using (TransactionScope tsc = new TransactionScope()) 
using (SqlConnection connection = new SqlConnection(...)) 
{ 
    connection.Open(); 
    OrderService os = new OrderService(connection); 
    os.ProcessOrder(myOrder); 
    ShippingService ss = new ShippingService(connection); 
    ss.ShipOrder(myOrder); 
    tsc.Complete(); 
} 

कौन सा सबसे अधिक संभावना जा रहा है तुम क्या चाहते हो सकता है, में:

public class OrderService 
{ 
    private SqlConnection connection; 

    public OrderService(SqlConnection connection) 
    { 
     if (connection == null) 
      throw new ArgumentNullException("connection"); 
     this.connection = connection; 
    } 

    // Other methods 
} 

यह तो आप सेवाओं के खिलाफ कोड निम्न के समान लिखने की अनुमति देता अंत - कई सेवाओं के बीच एक कनेक्शन साझा करने की क्षमता।

यह डेटा कनेक्शन के कार्यान्वयन विवरण से आपकी सेवाएं decouple आपकी सेवाओं में भी मदद करता है। इस तरह, यदि आप कुछ परिस्थितियों में कनेक्शन सेटिंग्स को बदलने जैसे कुछ करना चाहते हैं, तो आपको 50 अलग-अलग सेवाओं के विवरण में खोदने की ज़रूरत नहीं है, आपको केवल कोड की एक पंक्ति को बदलना होगा जो कनेक्शन बनाता है।

एक और बात: आप TransactionScope उपयोग करने के लिए जा रहे हैं,, कनेक्शन स्ट्रिंग को Transaction Binding=Explicit Unbind जोड़ना सुनिश्चित करें अन्यथा यह वास्तव में असंगत डेटा यदि किसी लेन-देन का समय समाप्त के साथ समाप्त करने के लिए संभव है।

+1

एमएसडीएन के अनुसार, ".NET Framework संस्करण 4 में शुरू होने से, लागू अनबिंड में परिवर्तन स्पष्ट अनबिंड अप्रचलित बनाते हैं।" http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.connectionstring(v=vs.100).aspx ग्रेट उत्तर और उदाहरण! – xkingpin

2

जैसा कि अन्य लोगों ने उल्लेख किया है, TransactionScope जाने का रास्ता है।

यदि आप SQL Server 2008 और .NET 3 का उपयोग कर रहे हैं।5, मैं व्यापार ऑब्जेक्ट को लेनदेन को नियंत्रित करने के लिए डिज़ाइन को संशोधित करता हूं और डेटा परत से कनेक्शन खोलने और बंद करने देता हूं।

कनेक्शन पूलिंग के साथ, आप वास्तव में भौतिक डेटाबेस कनेक्शन खोलने के ऊपरी हिस्से को नहीं ले पाएंगे और वास्तविक कनेक्शन करने पर आपके कनेक्शन केवल खुले रहेंगे। चूंकि (मैंने माना) आपके पास SQL Server 2008 with .NET 3.5 your transaction will not escalate to a distributed transaction है (जब तक आप एक ही समय में एकाधिक कनेक्शन नहीं खोलते) ताकि आप दोनों दुनिया के सर्वश्रेष्ठ प्राप्त कर सकें।

तो फिर तुम इस तरह अपने व्यापार वस्तु लिख सकते हैं:

using (TransactionScope transactionScope = new TransactionScope()) 
{ 
    DataObject dataObject = new DataObject(); 
    dataObject.UpdateQuantity(...); 

    ShippingManager shippingManager = new ShippingManager(); 
    shippingManager.ShipOrder(...); 

    transactionScope.Complete() 
} 

यह सब व्यापार वस्तुओं के लिए चारों ओर कनेक्शन तार पारित करने के लिए होने टाल और लेन-देन के समन्वय के लिए आसान बनाता है।

अद्यतन

System.Transactions की सुंदरता है कि लेन-देन के सभी कनेक्शन है कि आप प्रयोग कर रहे हैं पर ध्यान दिए बिना आप के लिए प्रबंधित कर रहे हैं है। आप बस एक लेनदेन स्कोप घोषित करते हैं और उस लेनदेनस्कोप के भीतर सभी डेटाबेस पहुंच एक लेनदेन के साथ होती है (जब तक कि आप अन्यथा विभिन्न लेनदेनस्कोप सेटिंग्स के साथ अनुरोध नहीं करते)।

अतीत में (SQL सर्वर 2005 .NET 2.0), यदि आपने कनेक्शन खोला और बंद कर दिया और फिर एक और कनेक्शन खोला और बंद कर दिया (यहां तक ​​कि एक ही कनेक्शन स्ट्रिंग के साथ) तो लेनदेन को लाइटवेट लेनदेन से वितरित किया गया लेन-देन। यह अवांछित था क्योंकि प्रदर्शन पीड़ित है (एमएसडीटीसी के लिए संचार प्रक्रिया से बाहर है और दो चरण प्रतिबद्ध प्रोटोकॉल) और एमएसडीटीसी कई उत्पादन वातावरण (फ़ायरवॉल और सुरक्षा) में कॉन्फ़िगर करने के लिए दर्द हो सकता है।

SQL सर्वर 2008 और .NET 3.5 के साथ उन्होंने एक ही लेनदेन के भीतर एक ही कनेक्शन स्ट्रिंग के साथ एकाधिक कनेक्शन खोलने और बंद करते समय इस पदोन्नति से बचने की क्षमता को जोड़ा है। Extending Lightweight Transactions in SqlClient को उन्होंने जो देखा वह वास्तव में अच्छी व्याख्या के लिए।

अद्यतन 2

Oracle 10g के साथ लेन-देन TransactionScope के साथ ठीक से कार्य करेंगे। और ऐसा लगता है कि ODP.NET supports Lightweight Transactions (जो अच्छा है)। दुर्भाग्य से, मुझे लगता है कि एक वितरित लेनदेन को बढ़ावा देना कनेक्शन के समापन और उद्घाटन के साथ होगा।

यदि आप एक वितरित लेनदेन से बचना चाहते हैं तो आप प्रत्येक विधि कॉल/बिजनेस ऑब्जेक्ट से कनेक्शन पास कर सकते हैं। यदि आप आसपास कनेक्शन को पास नहीं करना चाहते हैं, तो आप ConnectionScope class का उपयोग कर सकते हैं जो कनेक्शन को थ्रेड पर खुलता रहता है। इसका एक विकल्प एंटरप्राइज़ लाइब्रेरी 3.0 (और ऊपर) डेटा एक्सेस एप्लिकेशन ब्लॉक का उपयोग करना होगा। वितरित लेनदेन से बचने के लिए Data Access Block can detect that a transaction is in progress and use the same connection

+0

यदि आपके पास डेटा लेयर हैंडल खोलने और बंद कनेक्शन हैं, तो आप लेनदेन का उपयोग कैसे करते हैं? यदि आपके पास तीन बीओ हैं जो कुछ करने की ज़रूरत है और वे सभी एक ही लेनदेन पर हैं, तो क्या उन्हें सभी को एक ही कनेक्शन का उपयोग नहीं करना पड़ेगा? –

+0

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

1

आप शायद Unit of Work पैटर्न और Registry पैटर्न की तलाश कर रहे हैं। ये दो पैटर्न व्यावसायिक वस्तुओं को खोजने की चिंताओं को अलग करने और लेन-देन के रूप में बाद में आपके डेटा स्टोर में प्रतिबद्ध होने के लिए उन्हें ट्रैक करने के लिए संगीत कार्यक्रम में काम कर सकते हैं।

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

चूंकि आप सी # और .NET का उपयोग कर रहे हैं, इसलिए मैं एंटिटी फ्रेमवर्क (v4, v1 का उपयोग न करें), या LINQ से SQL में देखता हूं। दोनों या मैपर हैं जो v3.5 और बाद में .NET ढांचे के साथ आते हैं। LINQ से SQL एक बहुत ही सरल और अच्छी तरह से टूली हुई ओआरएम है जिसे आपको बहुत जल्दी जाना चाहिए। एंटिटी फ्रेमवर्क एक बहुत समृद्ध ओआरएम है जो कि बहुत अच्छी तरह से टूल किया गया है (LINQ से SQL से बेहतर), और काफी अधिक कार्यक्षमता प्रदान करता है। तीसरे पक्ष के ओआरएम भी हैं जो नौकरी कर सकते हैं, जिसमें एनएचबीर्नेट नामक एक मुक्त व्यक्ति शामिल है। हालांकि इसे माइक्रोसॉफ्ट ओआरएम के रूप में भी नहीं बनाया गया है, एनएचबीर्नेट एक बड़े समुदाय के साथ बहुत परिपक्व ओपन सोर्स ओआरएम है।

एक ORM एक संभावना नहीं है, तो फिर मैं Unit of Work, Registry (या भंडार) में विचार करेंगे, हठ अज्ञान, Separation of Concerns, Single Responsibility, और अन्य संबंधित पैटर्न।

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