5

में मॉडलबाइंडिंग डेटाबेस इकाइयां मुझे यह सोचने में परेशानी हो रही है कि नियंत्रक एक्शन में डेटाबेस ऑब्जेक्ट को फिर से बनाने का सबसे अच्छा तरीका क्या है।एएसपीएनईटी एमवीसी

मैं मॉडलबिंडर्स का उपयोग करना चाहता हूं, इसलिए मेरी क्रिया में मुझे पहचानकर्ता पैरामीटर के आधार पर डेटाबेस से ऑब्जेक्ट प्राप्त करने के लिए कोड दोहराने के बजाय पैरामीटर के माध्यम से ऑब्जेक्ट तक पहुंच है। तो मैं एक मॉडलबिंडर रखने की सोच रहा था जो मूल ऑब्जेक्ट प्राप्त करने के लिए डेटाकैस परत पर कॉल करता है (या डेटाबेस में मौजूद नहीं होने पर एक नया बनाता है), फिर डेटाबेस ऑब्जेक्ट को किसी भी गुण को अद्यतन करने के लिए बाध्य करता है। हालांकि मैंने पढ़ा है कि मॉडलबिंडर्स को डेटाबेस क्वेरी नहीं करना चाहिए (इस article की पहली टिप्पणी)।

यदि मॉडलबिंडर को डेटाबेस क्वेरी नहीं करना चाहिए (तो केवल डिफ़ॉल्ट मॉडेल बाइंडर का उपयोग करना चाहिए) तो डेटाबेस ऑब्जेक्ट्स के बारे में क्या है जिसमें अन्य डीबी ऑब्जेक्ट्स हैं? ये कभी सौंपा नहीं जाएगा।

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

तो, दृश्य से पोस्ट किए गए फॉर्म डेटा के साथ डेटाबेस से नियंत्रक कार्रवाई में ऑब्जेक्ट प्राप्त करने का सबसे अच्छा तरीका क्या है?

नोट एनएचबीर्नेट का उपयोग कर रहा हूं।

+0

मैं (आप के रूप में ठीक उसी स्थिति में हूँ भी एनएच का उपयोग)। मैंने कोड डुप्लिकेशन से बचने के लिए एक मॉडल बाइंडर लागू किया है। बाइंडर से डीबी तक पहुंचने के बारे में आपका निष्कर्ष क्या है? –

+0

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

+0

मुझे बताने के लिए धन्यवाद। –

उत्तर

4

मुझे डेटाबेस से मॉडल ऑब्जेक्ट मिलता है, फिर फॉर्म पैरामीटर से मान अपडेट करने के लिए ऑब्जेक्ट पर UpdateModel (या TryUpdateModel) का उपयोग करें।

public ActionResult Update(int id) 
{ 
    DataContext dc = new DataContext(); 
    MyModel model = dc.MyModels.Where(m => m.ID == id).SingleOrDefault(); 

    string[] whitelist = new string[] { "Name", "Property1", "Property2" }; 

    if (!TryUpdateModel(model, whitelist)) { 
     ... model error handling... 
     return View("Edit"); 
    } 

    ViewData.Model = model; 

    return View("Show"); 
} 
+1

मुझे पता चला है कि अगर मेरे पास मेरे मॉडल पर एक संपत्ति है जो कुछ मूल्य के लिए असाइन की गई है और यह फॉर्मकॉलेक्शन में मौजूद नहीं है, तो TryUpdateModel करते समय संपत्ति को शून्य में सेट किया जाता है, भले ही मैं गुणों को शामिल/बहिष्कृत करता हूं। तो मूल रूप से TryUpdateModel डेटा हानि का कारण बन रहा है, जो अच्छा नहीं है। –

+0

यह केवल उन गुणों को प्रतिस्थापित करना चाहिए जो श्वेतसूची में हैं यदि आपने एक निर्दिष्ट किया है। मुझे पता है कि यह काम करता है क्योंकि मेरे पास कुछ संपादन विचार हैं जो केवल कुछ मूल्यों को अपडेट नहीं कर सकते हैं। आप इसे सत्यापित करने के लिए http://www.codeplex.com/aspnet पर वास्तविक कोड देख सकते हैं। – tvanfosson

2

दुर्भाग्य से आप मॉडल बांधने की मशीन के निर्माण पर नियंत्रण नहीं है, तो आप किसी भी भंडार कार्यान्वयन इंजेक्षन नहीं कर सकते।

आप बाहर सीधे एक सेवा लोकेटर में अपने भंडार & में खींचने के लिए आइटम लाने तक पहुँच सकते हैं:

public class ProductBinder : DefaultModelBinder 
{ 
    protected override object CreateModel(ControllerContext controllerContext, 
     ModelBindingContext bindingContext, Type modelType) 
    { 
     if(modelType != typeof(Product)) 
      return null; 

     var form = controllerContext.HttpContext.Request.Form; 
     int id = Int32.Parse(form["Id"]); 
     if(id == 0) 
      return base.CreateModel(controllerContext, bindingContext, modelType); 

     IProductRepository repository = ServiceLocator.Resolve<IProductRepository>(); 

     return repository.Fetch(id);          
    }  
} 

तुम भी अपने संस्थाओं के सभी के लिए यह काम कर सकता है यदि आप एक आधार वर्ग का उपयोग कर सकते या इंटरफ़ेस जो कक्षा के आईडी प्रदान करता है।

आप Global.asax में सेट कर करना होगा:

ModelBinders.Binders.Add(typeof(Product), new ProductBinder()); 

और फिर आप यह कर सकते हैं:

public ActionResult Save([Bind] Product product) 
{ 
    .... 

    _repository.Save(product); 
} 
+0

यही वह है जो मैं मूल रूप से कर रहा था, क्योंकि यह मुझे यहां करने के लिए समझ में आता है। लेकिन कई स्थानों पर पढ़ा गया है कि मॉडलबिंडर को डेटाबेस से पूछताछ नहीं करनी चाहिए, इससे मुझे दो बार सोचा गया है। –

+1

यह थोड़ा सुगंधित है, लेकिन अगर यह आपको बेहतर महसूस करता है, तो कैसल प्रोजेक्ट से [एआरडाटाबिंड] बिल्कुल यही करता है। –

+1

डेटाबेस को मारना मोडबिंडर एक अच्छा विचार नहीं है। इसके अलावा, बाइंडर एक्शनफिल्टर से पहले निष्पादित करता है, इसलिए इसे ध्यान में रखें जब बाइंडर्स –

-1

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

+2

यह वास्तव में खतरनाक सलाह है। आपको अद्यतन से पहले हमेशा चयन करना चाहिए, क्योंकि ऐसे कई क्षेत्र हैं जहां आप डेटाबेस में सभी रिकॉर्ड्स अपडेट नहीं कर रहे हैं, जो खाली मूल्यों के साथ ओवरराइटिंग समाप्त कर देंगे। –

+0

बहुत सच, एक बेवकूफ जवाब था क्योंकि मैंने सवाल ठीक से नहीं पढ़ा था! –

0

मुझे पहले यह बताएं कि मैं मॉडलबिंडर्स से डेटाबेस तक पहुंचने की अनुशंसा नहीं करता हूं, क्योंकि कंसर्न मॉडल के पृथक्करण के परिप्रेक्ष्य से बाइंडर्स केवल ग्राहक अनुरोध की व्याख्या करने के लिए जिम्मेदार होना चाहिए, स्पष्ट रूप से डेटाबेस नहीं है।
आप अपने आप (सूखी), उपयोग खजाने/सेवाओं दोहराने के लिए लेकिन अगर यू वास्तव में उस तरह करना चाहते हैं Global.asax में तो

, नहीं चाहते हैं।सीएस रजिस्टर MVC

ModelBinderProviders.BinderProviders.Add(new EntityModelBinderProvider 
{ 
    ConnectionString = "my connection string" 
)); 

Cunstruct के लिए एक कस्टम MyModelBinderProvider डेटाबेस सेटिंग्स को रोकने के लिए

public class EntityBinderProvider: IModelBinderProvider 
{ 
    public string ConnectionString { get; set; } 

    public IModelBinder GetBinder(Type modelType) 
    { 
     if (Is known entity) 
      return new EntityBinder(ConnectionString); 
     else 
      return null; 
    } 
} 

बेन Scheirman से आगे निर्देशों का पालन करें कस्टम ModelBinderProvider

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