2012-08-13 10 views
6

का उपयोग कर एक एमवीसी रिपोजिटरी डिज़ाइन करना मैं अपने नियंत्रकों से अपने डेटा तर्क को अलग करने के लिए एक भंडार वर्ग बनाना चाहता हूं। मैं कुछ डेटा का प्रतिनिधित्व करने के लिए व्यूमोडेल का उपयोग कर रहा हूं जो विभिन्न तालिकाओं से डेटा भर जाएगा।ViewModels

यहाँ कुछ सवाल मेरे पास है कर रहे हैं:

  1. GetAll() की तरह एक विधि के लिए, मैं एक IQueryable<MyViewModel> या IQueryable<Entity> वापसी करते हैं? अगर मैं व्यूमोडेल लौटाता हूं, तो मैं GetAll() से कैसे निपटूं जो हजारों रिकॉर्ड खींचता है?
  2. क्या मैं अपने कस्टम व्यू मॉडेल क्लास के लिए एक कन्स्ट्रक्टर बनाता हूं जो मैपिंग करने के लिए इकाई को पैरामीटर के रूप में लेता है? (मैं अभी भी तो बस कैसे देखने के एक डिजाइन बिंदु से यह करने के लिए पर एक समझ की जरूरत है automapper से अपरिचित हूँ)

फिर, मेरी मुख्य चिंता GetAll() की तरह एक तरीका है जिसके कई रिकॉर्ड खींच होता है। यदि मैंने प्रत्येक इकाई को एक व्यूमोडेल में अनुवाद करने के लिए फ़ोरैच लूप किया है तो बहुत सारे ओवरहेड की तरह लगता है। मेरा विचार कस्टम व्यू मॉडेल क्लास के अंदर IQueryable<Entity> पर संग्रह से पहुंचने के लिए संदर्भ देना था, और ListViewModel में केवल इंडेक्सर्स या कुछ ऐसा है जो संग्रह संपत्ति का संदर्भ देता है।

उत्तर

5

1) GetAll() जैसी विधि के लिए, क्या मैं एक IQueryable या IQueryable वापस कर सकता हूं? अगर मैं व्यूमोडेल लौटाता हूं, तो मैं GetAll() से कैसे सामना करूं जो हजारों रिकॉर्ड खींचता है?

IQueryable<Entity>। भंडार दृश्य मॉडल से निपटता नहीं है। भंडार के बारे में सोचें जो एक अलग वर्ग पुस्तकालय में परिभाषित किया गया है जो आपके एएसपी.नेट एमवीसी अनुप्रयोग का संदर्भ नहीं देता है, जहां आपका दृश्य मॉडल रहता है। यह एएसपी.नेट एमवीसी एप्लीकेशन है जो इस पुस्तकालय का संदर्भ देता है।

2) क्या मैं अपने कस्टम व्यू मॉडेल क्लास के लिए एक कन्स्ट्रक्टर बनाता हूं जो मैपिंग करने के लिए इकाई को पैरामीटर के रूप में लेता है?

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

तो ऑटोमैपर या मैन्युअल रूप से मानचित्र करें।

मैनुअल मानचित्रण के साथ उदाहरण है जो क्या आप के साथ शुरू कर सकते हैं:

public ActionResult SomeAction() 
{ 
    IEnumerable<Entity> entities = Repository.GetAll(); 
    IEnumerable<MyViewModel> model = entities.Select(x => new MyViewModel 
    { 
     Prop1 = x.Prop1, 
     Prop2 = x.Prop2, 
     ... 
    }); 
    return View(model); 
} 

और जैसे ही आप AutoMapper के लिए इस कोड चाल को लिखा बीमार:

public ActionResult SomeAction() 
{ 
    IEnumerable<Entity> entities = Repository.GetAll(); 
    IEnumerable<MyViewModel> model = Mapper.Map<IEnumerable<Entity>, IEnumerable<MyViewModel>>(entities); 
    return View(model); 
} 

या आप एक कस्टम कार्रवाई लिखने अगर फ़िल्टर जो दृश्य में पारित डोमेन मॉडल को खींचने के लिए OnActionExecuted ईवेंट का उपयोग करता है, इसे ऑटोमैपर का उपयोग करके दृश्य मॉडल पर मैप करें और दृश्य के लिए दृश्य मॉडल के साथ मॉडल को प्रतिस्थापित करें, आप दोहराए गए कोड को और सरल बना सकते हैं:

[AutoMap(typeof(IEnumerable<Entity>), typeof(IEnumerable<MyViewModel>))] 
public ActionResult SomeAction() 
{ 
    IEnumerable<Entity> entities = Repository.GetAll(); 
    return View(entities); 
} 

फिर, मेरी मुख्य चिंता (GetAll की तरह एक विधि) जो कई रिकॉर्ड खींच होता है। अगर मैंने प्रत्येक इकाई को में अनुवाद करने के लिए फ़ोरैच लूप किया है तो ViewModel बहुत अधिक ओवरहेड की तरह दिखता है।

इसके बारे में चिंतित न हों। अपने रिकॉर्ड खींचकर दृश्य मॉडल में लूपिंग और मैपिंग की तुलना में धीमी गति होगी।

1

ऐसा करने के कई अलग-अलग तरीके हैं, लेकिन बस शुरू करने के लिए, मैं आपके GetAll() विधि के लिए IEnumerable<T> वापस कर दूंगा। हालांकि, आप शायद कुछ फैशन में पेजिंग को लागू करना चाहते हैं। आप एक सामान्य भंडार स्थापित करना चाहते हैं जो अधिकांश परिदृश्यों के लिए आपकी मूल डेटा पहुंच करता है और एक संख्यात्मक लौटाता है। आप एक ऐसी विधि को आरक्षित कर सकते हैं जिसे अधिक जटिल प्रश्नों के लिए आरक्षित किया जाना चाहिए और IQueryable<T> लौटाता है। बुनियादी छीनने का कार्यान्वयन नीचे जैसा दिख सकता है।

public class Repository<T> : IRepository<T> where T : class 
{ 
    internal ObjectContext _objectContext; 
    internal ObjectSet<T> _objectSet; 

    public Repository(ObjectContext objectContext) 
    { 
     _objectContext = objectContext; 
     _objectSet = objectContext.CreateObjectSet<T>(); 
    } 

    public IQueryable<T> GetQuery() 
    { 
     return _objectSet; 
    } 

    public IEnumerable<T> GetAll() 
    { 
     return GetQuery().ToList(); 
    } 

    public IEnumerable<T> Find(Func<T, bool> where) 
    { 
     return _objectSet.Where<T>(where); 
    } 

    public T Single(Func<T, bool> where) 
    { 
     return _objectSet.SingleOrDefault<T>(where); 
    } 

    public List<T> Page<TKey>(Expression<Func<T, bool>> where, int page, int pagesize, Expression<Func<T, TKey>> orderBySelector, bool ascending) 
    { 
     return ascending 
      ? GetQuery().Where(where).OrderBy(orderBySelector).Skip((page - 1) * pagesize).Take(pagesize).ToList() 
      : GetQuery().Where(where).OrderByDescending(orderBySelector).Skip((page - 1) * pagesize).Take(pagesize).ToList(); 
    } 


    public void Delete(T entity) 
    { 
     _objectSet.DeleteObject(entity); 
    } 

    public void Add(T entity) 
    { 
     _objectSet.AddObject(entity); 
    } 

} 

और इंटरफ़ेस लगेगा

तरह
public interface IRepository<T> where T : class 
{ 
    IQueryable<T> GetQuery(); 

    IEnumerable<T> GetAll(); 

    IEnumerable<T> Find(Func<T, bool> where);  

    T Single(Func<T, bool> where); 

    List<T> Page<TKey>(Expression<Func<T, bool>> where, int page, int pagesize, Expression<Func<T, TKey>> orderBySelector, bool ascending); 

    void Delete(T entity); 

    void Add(T entity); 

} 

एक सरल सामान्य भंडार की शुरुआत के रूप में ऊपर कर सकते हैं समारोह। एक बार जब आप अपनी संस्थाएं प्राप्त कर लेते हैं, तो आपको ऑटोमैपर की आवश्यकता नहीं होती है, यह केवल जीवन को आसान बनाता है क्योंकि कई व्यूमोडल्स के पास आपकी संस्थाओं के समान गुण होते हैं। आप बस एक नया ViewModel या ViewModels की सूची को परिभाषित कर सकते हैं और गुणों को मानचित्र बना सकते हैं।

List<ViewModel> vm = new List<ViewModel>(); 

foreach (var e in entities) 
{ 
    ViewModel v = new ViewModel(); 
    v.something = e.something; 
    // perform the rest 
    vm.Add(v); 
} 

* यह काफी टाइप करने के लिए एक सा, कोई लेखन त्रुटि :)

1

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

उदाहरण के लिए, आप GetAll() द्वारा लौटाई गई प्रत्येक इकाई के लिए एक अलग दृश्य मॉडल बनाना नहीं चाहते हैं। सभी रिकॉर्ड की एक gridview प्रदर्शित करने में एक सरल परिदृश्य में आप शायद सिर्फ एक संपत्ति के साथ एक एकल viewmodel की आवश्यकता होगी:

public class MyViewModel 
    {  
     public List<MyRecord> AllRecords {get;set;} 
    } 

आप नियंत्रक

public ActionResult SomeAction() 
{ 
    var viewmodel = new MyViewModel{AllRecords = GetAll()}; 
    return View(viewModel); 
} 

में इस दृश्य मॉडल हो जाएगी पर एक नज़र डालें वास्तव में संक्षिप्त चर्चा के लिए Rachael Appel द्वारा this blog post

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