2012-04-03 21 views
5

मैं निम्नलिखित ADO नेट भंडारIDisposable

public class Repository : IRepository, IDisposable 
{ 
    private readonly IUnitOfWork UnitOfWork; 
    private SqlConnection Connection; 

    public Repository(IUnitOfWork unitOfWork, connectionString) 
    { 
     UnitOfWork = unitOfWork; 
     Connection = new SqlConnection(connectionString); 
     Connection.Open(); 
    } 

    public MyObject FindBy(string userName) 
    { 
     //...Ado .Net command.ExecuteReader, etc. 
    } 
} 

यह भंडार एक डोमेन सेवा के लिए एक आईओसी कंटेनर के साथ इंजेक्ट किया जाता है और इतने की तरह इस्तेमाल किया जाता है:

public class UserDomainService : IUserDomainService 
{ 
    private readonly IRepository Repository; 

    public UserDomainService(IRepository repository) 
    { 
     Repository = repository; 
    } 

    public User CreateNewUser(User user) 
    { 
     using(Repository) 
     { 
     var user = Repository.FindBy(user.UserName); 
     if(user != null) 
      throw new Exception("User name already exists!"); 

     Repository.Add(user); 
     Repository.Commit(); 
     } 
    } 
} 

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

अब मैं सभी कोड का पूरा नियंत्रण है और मैं केवल मोटे अनाज सेवा कॉल डिजाइन करने के लिए चाहते हैं, लेकिन वहाँ पूरी बात है कि सही महसूस नहीं करता है के बारे में कुछ है।

मैं इसे इस तरह कर रहा हूँ तो मैं बच सकते हैं कि डोमेन सेवा भंडार में OpenConnection और CloseConnection तरीकों के बारे में जानता है।

इस डिजाइन स्वाभाविक बुरा है या ऐसा करने का एक बेहतर तरीका है?

सोचा के बाद: सभी निर्भरता पेड़ WCF स्तर पर बनाई जा रही है जब एक अनुरोध आता है और, बेशक आप देख सकते हैं कि कनेक्शन उस पल में खोला जाता है, क्योंकि यह भंडार के निर्माता में होता है तो मुझे विश्वास है कि यह बुरा नहीं है क्योंकि यह केवल इस विशेष कॉल की अवधि के लिए खुला है। क्या मैं इस धारणा पर सही हूं या क्या मैं प्रक्रिया में जल्दी ही डीबी कनेक्शन खोलकर बहुत बुरा कर रहा हूं?

+0

'आईआरपीपॉजिटरी 'निकटता से' रिपोजिटरी 'के साथ मिलकर है? मतलब, क्या इसमें इसके तरीके शामिल हैं, जैसे 'Find'? यदि हां, तो क्या यह इंटरफ़ेस 'IDISposable' का संकेत देता है? –

+0

मेरे पास मेरा स्वयं का प्रश्न है जो इससे संबंधित हो सकता है: [सर्विसकॉन्टेनर, आईओसी, और डिस्पोजेबल ऑब्जेक्ट्स] (http://stackoverflow.com/questions/556580/servicecontainer-ioc-and-disposable-objects)। –

+1

आपको 'रिपोजिटरी' में 'SqlConnection' क्यों चाहिए? आपके 'IUnitOfWork' के लिए कुछ और लगता है। – Steven

उत्तर

8

एक कारखाने कि उदाहरणों की जरूरत है, एक उदाहरण ही नहीं बनाता है सम्मिलित करें।

IRepositoryFactory लें ताकि आप IRepository बना सकें और हर बार इसका उपयोग करने का निपटान कर सकें। इस तरह, न तो डोमेन सेवा या कारखाने को डिस्पोजेबल होने की आवश्यकता होगी। साथ ही, और महत्वपूर्ण बात यह है कि, आप अभी भी हार्ड-कोडिंग के विरोध में कार्यान्वयन को इंजेक्ट करके कोड सार को रखते हैं।

public class UserDomainService : IUserDomainService 
{ 
    private readonly IRepositoryFactory RepositoryFactory; 

    public UserDomainService(IRepositoryFactory factory) 
    { 
     RepositoryFactory = factory; 
    } 

    public User CreateNewUser(User user) 
    { 
     using (IRepository repository = RepositoryFactory.Create()) 
     { 
     var user = repository.FindBy(user.UserName); 
     if(user != null) 
      throw new Exception("User name already exists!"); 

     repository.Add(user); 
     repository.Commit(); 
     } 
    } 
} 

आपको हमेशा जिस प्रकार की आवश्यकता है उसे इंजेक्ट करने की ज़रूरत नहीं है। कैसल विंडसर (जिसकी मानसिकता पंजीकरण-संकल्प-रिलीज है) पर पढ़ने पर, आप पाते हैं कि यदि आप ऐप के जीवन में एक अनिश्चित समय पर सामान को हल करना चाहते हैं, तो यह टाइप फैक्ट्रीज़ का उपयोग करने का सुझाव दिया जाता है।

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

+0

डीयूएच! मुझे नहीं पता कि मैंने इस बारे में क्यों नहीं सोचा था। धन्यवाद। –

+0

@ सर्जियोरोमेरो कभी-कभी आपको सही निष्कर्ष पर आने से पहले एक कदम वापस लेने और अन्य लोगों के साथ इस मुद्दे को समझने की आवश्यकता होती है। मैं इसे हर समय करता हूं, यदि आप हर समय घुटने टेकते हैं तो डिज़ाइन सर्कल में फंसना बहुत आसान होता है :-( –

+0

अब आपके पास एक लकीर अमूर्तता है। Encapsulation का उल्लंघन। सेवा को जीवन भर के बारे में जानने की आवश्यकता नहीं है भंडार का। आपने रहस्य प्रकट किया। सबसे अच्छा समाधान रिपोजिटरी को फिर से लिखना होगा ताकि यह प्रत्येक लेनदेन के लिए कनेक्शन खोला और बंद कर दिया जा सके। –

1

आपके पास समस्या स्वामित्व में से एक है। UserDomainService कक्षा IRepository नहीं बनाती है, फिर भी यह उस उदाहरण का स्वामित्व लेती है, क्योंकि यह इसे निपटाती है।

सामान्य नियम है कि जो एक वस्तु बनाता है यह distroy चाहिए। दूसरे शब्दों में, वह वस्तु जो वस्तु बनाता है वह मालिक है, और मालिक उस वस्तु को नष्ट कर देगा।

आपकी समस्या का दो समाधान कर रहे हैं।

  1. IRepositoryFactory बनाएं, जैसा कि एडम स्पष्ट रूप से बताता है।इस तरह के फैक्ट्री पर CreateNewRepository() विधि स्पष्ट रूप से संवाद करेगी कि कॉलर को स्वामित्व मिल जाता है और उसे बनाए गए भंडार का निपटान करना चाहिए।

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

अंतिम ध्यान दें, अपने IRepository औजार IDisposable। समाधान 2 चुनते समय, आप इंटरफ़ेस को IRepository से हटा सकते हैं, जो इस तथ्य को छुपाता है कि संसाधन एप्लिकेशन से शामिल हैं। आवेदन से IDisposable छिपाना एक अच्छी बात है, क्योंकि वह इंटरफ़ेस एक लकीर अमूर्त है। आवेदन के भीतर से Dispose पर कॉल करने के बाद से आप पहले से ही इसका सामना कर चुके हैं, पूरे एप्लिकेशन को तोड़ देता है।

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

  • कोई संबंधित समस्या नहीं^_^