2014-10-26 7 views
8

मैं अपने सिर को दिनों के साथ इस पर टक्कर लगी हूं और अभी भी यह तय नहीं कर सकता कि सही दृष्टिकोण कौन सा है।
यह सवाल WPF विशेष रूप से के बाद से के रूप में एक वेब आवेदन का विरोध, कई पोस्ट और लेख ऑनलाइन को लक्षित एक context प्रति view-model दृष्टिकोण और नहीं एक contextrequest प्रति की सिफारिश की है।
मेरे पास WPF MVVM एप्लिकेशन है जो Entity-Framework DB first मॉडल का उपयोग कर रहा है।डब्ल्यूपीएफ एमवीवीएम अनुप्रयोग में डीबीकॉन्टेक्स्ट प्रबंधित करना

public partial class User 
{ 
    public User() 
    { 
     this.Role = new HashSet<Role>(); 
    } 

    public string ID { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<Role> Role { get; set; } 
} 

public class Role 
{ 
    public Role() 
    { 
     this.User = new HashSet<User>(); 
    } 

    public int ID { get; set; } 
    public string Name { get; set; } 

    public virtual ICollection<User> User { get; set; } 
} 

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

1)
यहाँ (EF डिजाइनर द्वारा बनाई गई) मेरे एप्लिकेशन में इस्तेमाल किया दो मॉडल का एक उदाहरण है

public class Dal 
{ 
    public User GetUserById(object userId) 
    { 
     using (var db = new DbEntities()) 
     { 
      return db.User.Find(userId); 
      db.SaveChanges(); 
     } 
    } 

    public void RemoveUser(User userToRemove) 
    { 
     using (var db = new DbEntities()) 
     { 
      db.User.Remove(userToRemove); 
      db.SaveChanges(); 
     } 
    } 
} 

जो मैं अपने 01 में उपयोग कर सकते हैं: जो बनाता है और प्रत्येक विधि कॉल पर DbContext के disposes एक DataAccess वर्ग बनानाइस प्रकार है:

public class UserManagerViewModel : ObservableObject 
{ 
    private readonly Dal dal = new Dal(); 

    // models... 
    //commands... 
} 

2) इसी प्रकार 1 दृष्टिकोण लेकिन Using बयान के बिना:

public class Dal : IDisposable 
{ 
    private readonly DbEntities db = new DbEntities(); 
    public User GetUserById(object userId) 
    { 
     return db.User.Find(userId); 
     db.SaveChanges(); 

    } 

    public void RemoveUser(User userToRemove) 
    { 
     db.User.Remove(userToRemove); 
     db.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     db.SaveChanges(); 
    } 
} 

उपयोग अंदर ViewModel

3) ही है बनाएँ प्रत्येक entity के लिए repository। उपर्युक्त विकल्पों के समान दिखता है (using दुविधा के साथ या उसके बिना), हालांकि प्रत्येक संग्रह में केवल entity से संबंधित विधियां हैं।
अफैक का उपयोग मेरे ViewModel के अंदर जैसा ही है।

public class UnitOfWork : IDisposable 
{ 
    private DbEntities db = new DbEntities(); 

    private IUserRepository userRepository; 
    public IUserRepository UserRepository 
    { 
     get 
     { 
      return userRepository ?? new UsersRepository(db); 
     } 
    } 

    public void Save() 
    { 
     db.SaveChanges(); 
    } 

    public void Dispose() 
    { 
     db.Dispose(); 
    } 
} 

और मेरे ViewModel अंदर इसका इस्तेमाल इस प्रकार है::

4) एक Unit-Of-Work वर्ग कि मांग पर उचित Repository पारित करेंगे बनाएं

public class UserManagerViewModel : ObservableObject 
{ 
    private readonly UnitOfWork unit = new UnitOfWork(); 

    // models... 
    //commands... 
} 

ऊपर दृष्टिकोण से कौन सा (यदि कोई है) डेटा समेकन, बेहतर अमूर्तता और लेयरिंग और समग्र प्रदर्शन के संदर्भ में प्राथमिकता दी जाती है?
संपादित करें -this article. में निम्नलिखित पैरा मिला:

जब विंडोज प्रस्तुति फाउंडेशन (WPF) या Windows प्रपत्र के साथ काम करने, प्रपत्र प्रति एक संदर्भ उदाहरण का उपयोग करें। यह आपको परिवर्तन-ट्रैकिंग कार्यक्षमता का उपयोग करने देता है जो संदर्भ प्रदान करता है।

हालांकि, यह की कि मैं अपने view-model में एक DbContext वस्तु बनाना चाहिए प्रश्न उठाता है या यह बेहतर मेरी DAL वर्ग के रूप में एक उपयोगिता वर्ग इस तरह के है और यह संदर्भ के लिए है।

+3

ईएफ में एक उत्कृष्ट यूओडब्ल्यू (संदर्भ) + भंडार (डीबीसेट) है। अपना खुद का निर्माण क्यों करें? शायद ही कभी इन अतिरिक्त परतों सहायक हैं। वे डेटा-केंद्रित अनुप्रयोगों का नेतृत्व करते हैं जो व्यापारिक तर्क को क्लाइंट में खींचते हैं क्योंकि कार्य-केंद्रित अनुप्रयोगों के विपरीत जो ईएफ मॉडल के करीब सेवाओं में उपयोग मामलों को समाहित करते हैं। यह डेटा बनाम अमूर्त कार्यों का सार है (जहां अमूर्त मतलब है दृढ़ता कार्यान्वयन छिपाना)। –

+0

यह देखें http://mehdi.me/ambient-dbcontext-in-ef6/ – ErikEJ

+0

@GertArnold आपके उत्तर के लिए धन्यवाद। चूंकि मैं विशेष रूप से 'डब्ल्यूपीएफ एमवीवीएम' के बारे में पूछ रहा हूं, मुझे आश्चर्य है कि लंबे समय तक रहने वाले 'डीबीकॉन्टेक्स्ट' का उपयोग किया जाना चाहिए (एक 'संदर्भ' प्रति 'दृश्य-मॉडल') या क्या मुझे अपने 'संदर्भ' के जीवन काल को सीमित करना चाहिए विकल्प 1 ('उपयोग' का उपयोग करके :)) – Yoav

उत्तर

2

यह निर्भरता इंजेक्शन ढांचे को हल करने के लिए डिज़ाइन किया गया है। हां, यह आपकी परियोजना में जोड़ने के लिए एक और तकनीक है, लेकिन एक बार जब आप DI का उपयोग शुरू करते हैं तो आप कभी वापस नहीं देखते हैं।

वास्तविक समस्या यह है कि आप अपने विचार मॉडल में यह निर्णय लेने की कोशिश कर रहे हैं जब आपको वास्तव में नियंत्रण में उलझन में रहना चाहिए और निर्णय को ऊपर उठाना चाहिए। एक डब्ल्यूपीएफ/एमवीवीएम एप्लीकेशन एक संदर्भ प्रति-फॉर्म चाहता है ताकि परिवर्तन केवल उपयोगकर्ता द्वारा संपादित किए जाने के बाद ही सबमिट किया जा सके, और उपयोगकर्ता को परिवर्तनों को रद्द करने का अवसर भी प्रदान किया जा सके। मुझे पता है कि आप इसे वेब एप्लिकेशन में उपयोग नहीं कर रहे हैं लेकिन एक अच्छी तरह से डिज़ाइन किया गया आर्किटेक्चर का अर्थ है कि आपको सक्षम होना चाहिए, इस मामले में आप प्रति अनुरोध एक संदर्भ चाहते हैं। आप एक कंसोल-ऐप उपयोगिता लिखना चाह सकते हैं जो स्थिर डेटा के साथ डेटाबेस को पॉप्युलेट करता है, इस मामले में आप प्रदर्शन और आसानी से उपयोग के लिए वैश्विक/सिंगलटन संदर्भ चाहते हैं। अंत में, आपके यूनिट परीक्षणों को प्रति-परीक्षण आधार पर संदर्भ को नकल करने की भी आवश्यकता होती है। इन सभी चार मामलों को आपके इंजेक्शन ढांचे में स्थापित किया जाना चाहिए और आपके दृश्य मॉडल को उनमें से किसी के बारे में न तो पता होना चाहिए या उनकी परवाह नहीं करनी चाहिए।

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

var sessionBinding = Bind<ISession>().ToMethod(ctx => 
{ 
    var session = ctx.Kernel.Get<INHibernateSessionFactoryBuilder>() 
     .GetSessionFactory() 
     .OpenSession(); 
    return session; 
}); 

if (this.SingleSession) 
    sessionBinding.InSingletonScope(); 
else if (this.WebSession) 
    sessionBinding.InRequestScope(); 
else 
    sessionBinding.InScope(ScreenScope); 

यह एक ISession, जो आपके संदर्भ वर्ग के NHibernate बराबर है के लिए scoping सेट । [इंजेक्षन] विशेषता Ninject बताता है इस क्षेत्र को भरने के लिए स्वचालित रूप से scoping नियम मैं निर्धारित किया है का उपयोग कर

public class RepositoryManager : IRepositoryManager 
{ 
    [Inject] 
    public ISession Session { get; set; } 

    ... etc... 
{ 

: मेरी भंडार कक्षाएं, जो स्मृति में डेटाबेस वस्तुओं का प्रबंधन, वे के साथ जुड़े रहे सत्र के लिए एक संदर्भ शामिल अप। अब तक यह सब मेरे डोमेन वर्गों में हो रहा है, लेकिन यह मेरे दृश्य मॉडल परत तक भी विस्तारित है। मेरे स्कोपिंग नियमों में मैं "स्क्रीनस्कोप" नामक किसी ऑब्जेक्ट में जाता हूं, और जब मैं इसमें नहीं जाऊंगा, तो मूल रूप से इसका अर्थ यह है कि जब भी मैं अपने स्क्रीन व्यू मॉडेल में सत्र ऑब्जेक्ट के लिए पूछता हूं, या किसी भी दृश्य मॉडल जो उसके सदस्यों के रूप में होता है (अपने बच्चों सहित) एक ही ISession ऑब्जेक्ट स्वचालित रूप से बनाया जाता है और उन सभी को पास कर दिया जाता है। डि scoping का उपयोग करके मैं भी इसके बारे में सोचने के लिए, मैं सिर्फ [इंजेक्षन] विशेषता के साथ सदस्यों की घोषणा की जरूरत नहीं है और ऐसा होता है:

public class ScreenViewModel 
{ 
    [Inject] public CustomerService CustomerService { get; set; } 
    [Inject] public SalesService SalesService { get; set; } 
    [Inject] public BillService BillService { get; set; } 
    ...etc... 
} 

इन सेवा वर्गों सब एक RepositoryManager कि इंजेक्शन की जा चुकी है, और चूंकि वे सभी ScreenViewModel में हैं, कम से कम मेरे WPF निर्माण में, ISession ऑब्जेक्ट समान होगा। अगर मैं अपने एमवीसी बिल्ड में स्विच करता हूं तो वे दिए गए अनुरोध के लिए बनाए गए सभी दृश्य मॉडल के लिए समान होते हैं, और यदि मैं कंसोल बिल्ड पर स्विच करता हूं तो यह पूरे कार्यक्रम में सब कुछ के लिए एक ही ISession का उपयोग करता है।

टीएल; डीआर: निर्भरता इंजेक्शन का उपयोग करें और अपने संदर्भों को एक-प्रति-फॉर्म में एक दायरा का उपयोग करें।

+0

मैं यूआई टॉपोइक में DI पर शोध कर रहा हूं, और मैं संदर्भ प्रति ईवेंट/कमांड बनाना चाहता हूं (डब्ल्यूपीएफ के मामले में)। दुर्भाग्यवश मुझे यह नहीं पता कि इसे कैसे कार्यान्वित किया जाए :(केवल समाधान जो मैं देख सकता हूं, इंजेक्शन को विधि तर्क के रूप में पास करना है, लेकिन वह सुंदर बेकार है –

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