2010-11-28 2 views
31

ईएफ से नया और मैंने देखा है कि एक भंडार पैटर्न का उपयोग करके चीजों को वास्तव में सरल बना सकते हैं और मुझे कुछ मजाक करने की भी अनुमति होगी। अब तक बहुत अच्छा है।एंटीटी फ्रेमवर्क 4 में रिपोजिटरी पैटर्न जब हमें निपटान करना चाहिए?

मेरे प्रश्न

ObjectContext का एक विशिष्ट उपयोग नीचे

using (var context = new SchoolEntities()) 
{  
    context.AddToDepartments(department);  
    context.SaveChanges(); 
} 

देख भंडार पैटर्न का उपयोग करते हुए मैंने देखा है कि कोई भी वास्तव में "का उपयोग पैटर्न" का उपयोग करता है जितनी जल्दी हो सके नष्ट करने के लिए है जैसे

using (var repository= new Repository<Student>(new MyContext)) 
{  
    repository.Add(myStudentEntity) 
    repository.SaveChanges(); 
} 

क्या विचार होना चाहिए कि हमें जल्द से जल्द संदर्भ का निपटान करना चाहिए अन्यथा स्मृति रिसाव हो सकती है या बहुत बड़ी हो सकती है?

कोई भी स्पष्टीकरण दे सकता है? बहुत बहुत धन्यवाद।

उत्तर

47

हाँ यदि आप भंडार का उपयोग कर रहे हैं तो भी आपको संदर्भ का निपटान करना चाहिए। यह स्पष्ट नहीं है कि आपका रिपोजिटरी कार्यान्वयन आपको क्या लाभ देता है क्योंकि आप अभी भी ऑब्जेक्ट कॉन्टेक्स्ट को कन्स्ट्रक्टर के पैरामीटर के रूप में प्रदान कर रहे हैं, है ना?

आईएमओ रिपोजिटरी और कस्टम यूनिटऑफवर्क का उपयोग करने का मुख्य कारण है निरंतर अज्ञानता = ऊपरी अनुप्रयोग परतों से ईएफ कोड को हाइड करना क्योंकि ऑब्जेक्टकॉन्टेक्स्ट + ऑब्जेक्टसेट खुद को रिपोजिटरी और कार्य पैटर्न की इकाई का कार्यान्वयन कर रहा है।

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

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

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

UnitOfWork और भंडार पैटर्न के कुछ शुरू करने कार्यान्वयन: खजाने के लिए

प्रसंग धारक और अमूर्त कारखाने अलग संस्थाओं

के लिए

public interface IUnitOfWork 
{ 
    IRepository<MyEntity> MyEntityRepository { get; } 
    // Repositories for other entities 

    SaveChanges(); 
} 

भंडार

public interface IRepository<T> where T : class 
{ 
    IQueryable<T> GetQuery(); 
    void Insert(T entity); 
    void Delete(T entity); 

    // In very complex scenarios with big object graphs you will probably give up 
    // using detached approach and you will always load your entities from DB before 
    // deleting or updating them. In such case you will not need Update method at all. 

    void Update(T entity); 
} 

UnitOfWork Enitity ढांचे

लपेटकर के डिस्पोजेबल कार्यान्वयन
public class UnitOfWork : IUnitOfWork, IDisposable 
{ 
    private ObjectContext _context = null; 

    public UnitOfWork(string connectionString) 
    { 
    if (String.IsNullOrEmpty(connectionString)) throw new ArgumentNullException("connectionString"); 
    _context = new ObjectContext(connectionString); 
    } 

    private IRepository<MyEntity> _myEntityRepository; 

    public IRepository<MyEntity> MyEntityRepository 
    { 
    get 
    { 
     return _myEntityRepository ?? (_myEntityRepository = new GeneralRepository<MyEntity>(_context)); 
    } 
    } 

    public void SaveChanges() 
    { 
    _context.SaveChanges(); 
    } 

    public void Dispose() 
    { 
    Dispose(true); 
    GC.SuppressFinalize(this); 
    } 

    protected virtual void Dispose(bool disposing) 
    { 
    if (disposing) 
    { 
     if (_context != null) 
     { 
     _context.Dispose(); 
     _context = null; 
     } 
    } 
    } 
} 

बेस भंडार कार्यान्वयन

public class GeneralRepository<T> : IRepository<T> where T : class 
{ 
    private ObjectSet<T> _set; 
    private ObjectContext _context; 


    public GeneralRepository(ObjectContext context) 
    { 
    if (context == null) throw new ArgumentNullException("context"); 
    _context = context; 
    _set = context.CreateObjectSet<T>(); 
    } 

    // Override this method for example if you need Includes 
    public virtual IQueryable<T> GetQuery() 
    { 
    return _set; 
    } 

    // Override following methods if you are working with object graphs. 
    // Methods do not execute operations in database. It is responsibility of 
    // UnitOfWork to trigger the execution 

    public virtual void Insert(T entity) 
    { 
    if (entity == null) throw new ArgumentNullException("entity"); 
    _set.AddObject(entity); 
    } 

    // These impelementations are for detached scenarios like web application 

    public virtual void Delete(T entity) 
    { 
    if (entity == null) throw new ArgumentNullException("entity"); 
    _set.Attach(entity); 
    _set.DeleteObject(entity); 
    } 

    public virtual void Update(T entity) 
    { 
    if (entity == null) throw new ArgumentNullException("entity"); 
    _set.Attach(entity); 
    _context.ObjectStateManager.ChangeObjectState(entity, EntityState.Modified); 
    } 
} 

प्रयोग जब डेटा

using (var uow = new UnitOfWork(connectionString)) 
{ 
    var entity = uow.MyEntitiesRepository.GetQuery().Single(e => e.Id == 1); 
    // Do something with entity 
} 

प्रयोग का चयन जब डेटा

using (var uow = new UnitOfWork(connectionString)) 
{ 
    uow.MyEntitiesRepository.Update(entity); 
    uow.SaveChanges(); 
} 
+1

Fantastic.Thanks modifing !!! इन रिपॉजिटरीज के साथ मेरे पास एकमात्र मुद्दा यह है कि उनमें से कोई भी "शामिल" उत्सुक लोडिंग को संभाल नहीं करता है। आप अपने भंडार के साथ उत्सुक लोडिंग कैसे करते हैं? – user9969

+1

यह मुश्किल हिस्सा है, क्योंकि EF ObjectQuery की विशेषता शामिल है। मैं आम तौर पर GeneralRepository से विरासत भंडार बना रहा हूं और आवश्यक जोड़ों को अधिग्रहण में शामिल करता हूं GetQuery। लेकिन अगर आपको केवल कुछ प्रश्नों के लिए उत्सुक लोडिंग सक्रिय करने की आवश्यकता है तो यह आपकी मदद नहीं करेगा। उस स्थिति में आपको कुछ और चाहिए। मैं लिंक-टू-एसक्यूएल से लोडऑप्शन जैसे कुछ को कार्यान्वित करने और यूनिटऑफवर्क या रिपोजिटरी में इस विकल्प को पारित करने की कल्पना कर सकता हूं। फिर सभी सेट करने के लिए ऑप्टिन्स का उपयोग करना शामिल है। –

+2

बहुत गहराई से जवाब में - हालांकि, आपकी 'यूनिटऑफवर्क' कक्षा में एक एकल, स्थानीय-स्कोप्ड 'आईरिपोजिटरी 'उदाहरण है, जिसका अर्थ है कि कार्य इकाई यूनिट के साथ काम करने के लिए परिभाषित कर रही है। यह सही नहीं है। कार्य इकाई का बिंदु कई भंडारों में लेनदेन को संभालना है (यूओडब्ल्यू आमतौर पर अपने सीटीओ के माध्यम से 1- * भंडार स्वीकार करता है)। यह कार्यान्वयन वास्तव में इसे बिल्कुल संभाल नहीं करता है। हालांकि ओपी के लिए यह ठीक है। – RPM1984

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