2012-07-03 12 views
9

एएसपी.नेट एमवीसी प्रोजेक्ट में हम संपादन मॉडल/पोस्टमोडेल को कैसे परिवर्तित करें हम डोमेन मॉडल से देखने के लिए ऑटोमैपर का उपयोग कर रहे हैं - और कभी-कभी ऐसा करने के दौरान पदानुक्रम को भी फ़्लैट करना। यह एक आकर्षण की तरह काम करता है और हमारे विचारों के प्रतिपादन तर्क को बहुत दुबला और सरल बनाता है।डोमेन मॉडल

भ्रम शुरू होता है जब हम डोमेन मॉडल के लिए viewmodel (या postmodel या editmodel) से अन्य रास्ते जाने के लिए, खासकर जब अद्यतन करने वस्तुओं चाहते हैं। हम स्वचालित नहीं कर सकते का उपयोग/दो तरह मानचित्रण है क्योंकि:

  1. हम चपटा पदानुक्रम
  2. डोमेन मॉडल पर सभी गुण unflat को परिवर्तनशील होना चाहिए था होता/सार्वजनिक setters
  3. परिवर्तन दृश्य से आने से हमेशा डोमेन पर वापस मैप किए जाने वाले फ्लैट गुण नहीं होते हैं, लेकिन कभी-कभी "ChangeManagerForEmployee()" या इसी प्रकार की विधियों को कॉल करने की आवश्यकता होती है।

यह भी जिमी Bogards लेख में वर्णित है: The case for two-way mapping in AutoMapper, लेकिन इस का हल विस्तार से वर्णन किया नहीं है, केवल कि वे जाना:

EditModel से CommandMessages के लिए - loosely- से जा रहा संपादित मॉड्यूल दृढ़ता से टाइप किए गए संदेशों को तोड़ने के लिए टाइप किया गया। एक एकल संपादन मॉडल आधा दर्जन संदेश उत्पन्न कर सकता है।

एक समान SO question में Mark Seeman द्वारा एक जवाब है, जहां वह उल्लेख है कि वहाँ

हम सार मानचित्रकारों और सेवाओं का उपयोग एक डोमेन वस्तु

लेकिन विवरण के लिए एक PostModel मैप करने के लिए - वैचारिक और तकनीकी कार्यान्वयन - छोड़ दिया गया है।

हमारे विचार अभी के लिए है:

  1. प्राप्त नियंत्रक की कार्रवाई विधि में एक FormCollection
  2. मूल डोमेन मॉडल प्राप्त करें और viewModelOriginal और viewModelUpdated
  3. viewModelUpdated UpdateModel() का उपयोग करते हुए FormCollection विलय करने के लिए इसे समतल
  4. viewModelOriginal की तुलना करने के लिए कुछ सामान्य सहायक विधि का उपयोग करें ViewModelUpdated
  5. या तो ए) उत्पन्न करें CommandMessages एक ला जिमी Bogard या बी) गुण और विधियों (शायद सीधे AutoMapper के माध्यम से) 1-1 गुण मानचित्रण के माध्यम से डोमेन मॉडल में सीधे मतभेद Mutate

कोई कैसे वे के माध्यम से FormCollection से आते हैं के कुछ उदाहरण प्रदान कर सकते हैं डोमेन मॉडल में editmodel/postmodel? "कमांड मैसेज" या "अमूर्त मैपर और सेवाएं"?(- मुझे लगता है कि इस अवधारणा को आप अनदेखा कर रहे थे हो सकता है कमान क्वेरी जिम्मेदारी पृथक्करण), संभवतः भी घटना सोर्सिंग के साथ

[HttpPost] 
public ActionResult Update(UpdateProductViewModel viewModel) 
{ 
    // fetch the domain model that we want to update 
    Product product = repository.Get(viewModel.Id); 

    // Use AutoMapper to update only the properties of this domain model 
    // that are also part of the view model and leave the other properties unchanged 
    AutoMapper.Map<UpdateProductViewModel, Product>(viewModel, product); 

    // Pass the domain model with updated properties to the DAL 
    repository.Update(product); 

    return RedirectToAction("Success"); 
} 
+1

यदि मैं कर सकता तो मैं यह प्रश्न एक हजार अपवॉट्स दूंगा। मैं इस के ठोस जवाब के लिए अंतहीन खोज कर रहा हूं। – devuxer

+0

अंत में आप किस प्रक्रिया के साथ गए थे? –

+0

हाय टॉम। हमने एक मिश्रण और मिलान समाधान का उपयोग करके समाप्त किया, जहां हम 1. डीएएल/डीबी से डोम ऑब्जेक्ट पुनर्प्राप्त करते हैं, 2. डोम ऑब्जेक्ट को व्यूमोडेल पर फ़्लैट करें, 3. ViewModel पर फॉर्मकॉल के साथ TryUpdateModel का उपयोग करें, 4।सरल गुणों पर फ़्लैटेड व्यूमोडेल से डोम (पदानुक्रम) तक रिवर्स मैपिंग करने के लिए ऑटोमैपर का उपयोग करें और 5. व्यूमोडेल से डोम विधियों (डोम ऑब्जेक्ट और/या डोम सर्विस) से गैर-तुच्छ गुणों को मैप करने के लिए सेवा का उपयोग करें। उम्मीद है कि यह मदद करता है - मुझे यकीन नहीं है कि कौन सा जवाब सही के रूप में चिह्नित करने के लिए है, क्योंकि यह एक से अधिक का मिश्रण है ...? –

उत्तर

1

मैं निम्नलिखित पैटर्न का उपयोग करें।

यह मूल रूप से डेटा स्रोत से पढ़ने और डेटा स्रोत पर लिखने के तर्क को अलग करने का एक अभ्यास है, इसका अर्थ यह भी हो सकता है कि पढ़ने और लिखने के लिए अलग-अलग डेटा मॉडल हो।

यह एक अच्छी जगह शुरू करने के लिए हो सकता है: http://abdullin.com/cqrs/

+0

हाय डारिन, आपके उत्तर के लिए धन्यवाद, लेकिन मैं देख रहा हूं कि फ़्लैट किए गए व्यूमोडेल को डोमेन मॉडल पदानुक्रम/कुल मिलाकर मैपिंग/गुणों के माध्यम से न केवल म्यूटिंग/गुणों के माध्यम से परिवर्तित करना और विधियों का उपयोग करना। –

+0

लगता है कि इस पैटर्न के परिणामस्वरूप अस्पष्ट मैपिंग डोमेन ऑब्जेक्ट में होगा। – Artyom

1

आप CQRS विचार करना चाह सकते:

+0

हाय Pawel, thx मैं पहले सीजीआरएस देख रहा था, शायद मैं इसे फिर से देखूँगा। मेरे पास तर्क से अलग होने के तरीके पर पहले से ही कुछ विचार हैं, लेकिन मैं विशेष रूप से कमांड संदेशों के माध्यम से फॉर्म मॉडल/एडिटमोडेल को डोमेन मॉडल में अनुवाद करने का तरीका देख रहा हूं, लेकिन मुझे कैसे पता चलेगा कि कौन से संदेश बनाना है? या यदि सेवाएं कर रहे हैं (अमूर्त मैपर) मुझे कैसे पता चलेगा कि क्या बदल गया है? मेरे संपादन मॉडल में केवल परिवर्तनों का नतीजा है, न कि परिवर्तन/संदेश स्वयं। –

+0

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

+0

यह सही है, मेरे पास एक बड़ा संपादन फ़ॉर्म है जो फ़्लैटेड व्यू मॉडल से भरा हुआ है। जब उपयोगकर्ता नियंत्रक को फॉर्म को संपादित और पोस्ट करता है तो मैं नहीं देख सकता कि कौन से फ़ील्ड बदल दिए गए हैं। मेरा विचार है "पहले" और "बाद" व्यूमोडल्स के सेट की तुलना करना (_ मूल जो भर गया था और एक अद्यतन जो मूल + मर्ज किए गए फॉर्म पोस्ट मानों को अद्यतन करता है UpdateModel_) और उसके बाद वहां से आदेश उत्पन्न करता है (सर्वर-साइड)। तो मुझे लगता है कि यह "UI" से आपका क्या मतलब है: यूआई क्लाइंट-साइड जेएस या यूआई में सर्वर-साइड व्यू + कंट्रोलर के रूप में है? –

0

विकल्प C: यह सब नियंत्रक कार्रवाई में रख दें। अगला, अगर वह बालों वाली हो जाती है, सेवाओं (अमूर्त मैपर) या संदेश-जैसी-विधियों (कमांड संदेश मार्ग) में विघटित हो जाती है।

कमान संदेश रास्ता:

public ActionResult Save(FooSaveModel model) { 
    MessageBroker.Process(model); 

    return RedirectToAction("List"); 
} 

और प्रोसेसर:

public class FooSaveModelProcessor : IMessageHandler<FooSaveModel> { 

    public void Process(FooSaveModel message) { 
     // Message handling logic here 
    } 

} 

यह वास्तव में है बस नियंत्रक कार्रवाई से बाहर है और अलग-अलग, विशेष संचालकों में फार्म की "संसाधन" जाने के बारे में ।

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

+0

हाय जिमी, आपके उत्तर के लिए thx। मैं निश्चित रूप से बालों को चीजों को पाने और अपने नियंत्रकों को हल्के वजन रखने की कोशिश नहीं कर रहा हूं [एएसपी.नेट एमवीसी 4 एक्शन में] (http://manning.com/palermo3/)। मैं कमांड संदेशों को भी देख रहा हूं (उदाहरण के लिए [यहां] (http://codebetter.com/iancooper/2011/04/27/why-use-the-command-processor-pattern-in-the-service-layer /) और "पुस्तक में एक एप्लिकेशन बस का उपयोग करना"), लेकिन आप कैसे जानते हैं कि आपके FooSaveModel में क्या बदल गया है? वेबफॉर्म के पुराने दिनों में मेरे पास मेरे CurrentManager-Dropdown से एक चयनित इंडेक्स चेंज किया गया ईवेंट होगा। अब मेरे पास FooSaveModel का अंतिम परिणाम है? –

+0

जिमी, 'प्रक्रिया के अपने कार्यान्वयन (FooSaveModel संदेश)' [सुझाव मैं पावेल के लिए किए गए] (http://stackoverflow.com/questions/11313822/how-to-mutate-editmodel-postmodel-to- करने के समान होगा डोमेन मॉडल # comment14932448_11320582)? यही है, आप वास्तव में "पहले" और "बाद" सेवकों को देखने के लिए नहीं देखते हैं कि क्या बदल गया है, लेकिन इसके बजाय SaveModel को सीधे DomainModel से तुलना करें और मानचित्र करें, वैकल्पिक रूप से आवश्यक विधियों को कॉल करें (उदा। 'चेंजमेनर() ')? –

+0

आपको देखभाल करने की आवश्यकता क्यों होगी कि क्या बदल गया है या नहीं? अगर मुझे विशिष्ट क्षेत्रों को बदलने के बारे में परवाह है, तो यह संकेत दे सकता है कि मुझे कार्य-विशिष्ट इंटरफेस (और सत्यापन) के साथ और अधिक स्क्रीन चाहिए। –

0

यहां कुछ समानताएं हैं जो मैं कर रहा हूं। दृश्य मॉडलों का मेरा पदानुक्रम केवल कुछ हद तक अपने डोमेन ऑब्जेक्ट समकक्षों से चपटा हुआ है, लेकिन मुझे बस रिवर्स मैपिंग के बजाए बाल संग्रह में जोड़ने, महत्वपूर्ण मूल्यों को बदलने जैसी चीजों को करने के लिए सहेजने के लिए स्पष्ट सेवा विधियों को कॉल करने से निपटना होगा। मुझे स्नैपशॉट्स के पहले और बाद में तुलना करना पड़ता है।

मेरी बचत अजाक्स को एमवीसी एक्शन में जेएसओएन के रूप में पोस्ट किया गया है और यह क्रियाएं एमवीसी द्वारा दृश्य मॉडल संरचना में जादुई रूप से बंधी हुई हैं। मैं फिर शीर्ष स्तर दृश्य मॉडल और उसके वंशजों को इसके समकक्ष डोमेन संरचना में बदलने के लिए ऑटोमैपर का उपयोग करता हूं। मैंने उन मामलों के लिए कई कस्टम ऑटोमैपर आईटीइप कन्वर्टर्स को परिभाषित किया है जहां क्लाइंट पर एक नया बच्चा आइटम जोड़ा गया है (मैं Knockout.js का उपयोग कर रहा हूं) और मुझे एक स्पष्ट सेवा विधि कॉल करने की आवश्यकता है। कुछ की तरह:

  foreach (ChildViewModel childVM in viewModel.Children) 
     { 
      ChildDomainObject childDO = domainObject.Children.Where(cdo => cdo.ID.Equals(childVM.ID))).SingleOrDefault(); 
      if (childDO != null) 
      { 
       Mapper.Map<ChildViewModel, ChildDomainObject>(childVM, childDO); 
      } 
      else 
      { 
       MyService.CreateChildDO(someData, domainObject); // Supplying parent 
      } 
     } 

मैं हटाता के लिए एक समान बात है और इस प्रक्रिया cascades काफी अच्छी तरह से पूरी संरचना के माध्यम से नीचे है। मुझे लगता है कि एक चपटा हुआ संरचना या तो काम करना आसान हो सकता है या कठिन हो सकता है - मेरे पास एक आईडी के साथ एक सारडोमेन व्यूमोडेल है जिसके साथ मैं उपरोक्त मिलान करता हूं, जो मदद करता है।

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