2013-06-18 7 views
9

मेरे पास एक मॉडल है जो मुझे POST अनुरोध से मिलता है। चूंकि मेरा विचार अपने पीओसीओ प्रकार को परिभाषित करता है, इसलिए सबमिट किए गए डेटा से बनाई गई वस्तु भी एक पॉको है। एक पीओसीओ होने के नाते, इसमें विभिन्न वर्चुअल गुण ओवरराइड नहीं होते हैं। इसलिए, उन वर्चुअल गुण शून्य वापस आते हैं। बदले में, इसका मतलब है कि मुझे अपनी संपत्तियों के माध्यम से नेविगेट करने के लिए विदेशी कुंजी के आधार पर अलग-अलग प्रश्न बनाना पड़ता है (यदि मैं इसे सहेजने से कहीं अधिक जटिल करना चाहता हूं)।मेरे पास एक पॉको है, क्या मुझे डीबीकॉन्टेक्स्ट से प्रॉक्सी मिल सकती है?

क्या मैं अपने मॉडल के पीओसीओ को दे सकता हूं, प्रॉक्सी प्राप्त कर सकता है जिसमें सभी ओवरराइड कार्यक्षमता है?

(मैं मान लिया था कि यह क्या db.Entry().Entity के लिए था, लेकिन यह अभी भी मुझे POCO वस्तु, नहीं प्रॉक्सी। मैं माउस द्वारा वस्तु के क्रम प्रकार का निरीक्षण कर रहा हूँ ब्रेकप्वाइंट विराम के दौरान रिटर्न है।)

+0

संभावित डुप्लिकेट [एंटीटीफ्रेमवर्क में प्रॉक्सी ऑब्जेक्ट में POCO ऑब्जेक्ट को कनवर्ट करें] (http://stackoverflow.com/questions/8174200/convert-poco-object-to-proxy-object-in-entityframework) – Dennis

उत्तर

7

इस कोड की तर्ज पर कुछ भी आपको चाहिए जो आपको चाहिए। मैंने automapper का उपयोग किया है ताकि पारित इकाई से मूल्यों को प्रतिलिपि संस्करण में कॉपी किया जा सके।

कोड जांचता है कि उत्तीर्ण इकाई एक प्रॉक्सी है या नहीं और तदनुसार इसे संभालती है।

public class Repository<T> where T : class 
{ 
    private readonly Context context; 
    private bool mapCreated = false; 
    public Repository(Context context) 
    { 
     this.context = context; 
    } 

    protected virtual T InsertOrUpdate(T e, int id) 
    { 
     T instance = context.Set<T>().Create(); 
     if (e.GetType().Equals(instance.GetType())) 
      instance = e; 
     else 
     { 
      if (!mapCreated) 
      { 
       Mapper.CreateMap(e.GetType(), instance.GetType()); 
       mapCreated = true; 
      } 
      instance = Mapper.Map(e, instance); 
     } 

     if (id == default(int)) 
      context.Set<T>().Add(instance); 
     else 
      context.Entry<T>(instance).State = EntityState.Modified; 

     return instance; 
    } 
} 

अद्यतन संस्करण के रूप में टिप्पणी में @Colin द्वारा वर्णित है कि automapper

public class Repository<T> where T : class 
{ 
    private readonly Context context; 
    public Repository(Context context) 
    { 
     this.context = context; 
    } 

    protected virtual T InsertOrUpdate(T e, int id) 
    { 
     T instance = context.Set<T>().Create(); 
     if (e.GetType().Equals(instance.GetType())) 
     { 
      instance = e; 
     } 
     else 
     { 
      DbEntityEntry<T> entry = context.Entry(instance); 
      entry.CurrentValues.SetValues(e); 
     } 

     context.Entry<T>(instance).State = 
      id == default(int) 
       ? EntityState.Added 
       : EntityState.Modified; 

     return instance; 
    } 
} 
+1

आपको बहुत बहुत धन्यवाद ! यह बिल्कुल वैसा ही है जो मुझे विभिन्न मॉडल प्रकारों के लिए सही मूल्यों के साथ उचित प्रॉक्सी प्राप्त करने की आवश्यकता है। –

+1

@TheodorosChatzigiannakis मैंने कोड प्रविष्टि 'के सामान्य संस्करण का उपयोग करने के लिए अद्यतन किया है। – qujck

+0

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

0

की जरूरत नहीं है आप MVC नियंत्रक के माध्यम से ऐसा करना चाहते हैं, तो आप की तरह कुछ का उपयोग कर सकते यह एक क्रिया के रूप में:

[HttpPost] 
    public ActionResult Update(int? id, FormCollection form) 
    { 
     // assumes repository will handle 
     // retrieving the entity and 
     // including and navigational properties 
     var entity = repository.Get(id); 
     if (entity == null) 
     { 
      throw new InvalidOperationException(string.Format("Not found: {0}", id)); 
     } 
     if (TryUpdateModel(entity)) 
     { 
      try 
      { 
       // 
       // do other stuff, add'l validation, etc 
       repository.Update(entity); 
      } 
      catch (Exception ex) 
      { 
       // 
       // exception cleansing/handling 
       // add'l model errors 
       return View(entity); 
      } 
      return View("Success", entity); 
     }    

     return View(entity); 
    } 
+0

आपके उत्तर के लिए धन्यवाद! यह एक मान्य दृष्टिकोण है और वास्तव में, जो मैं पहले से उपयोग कर रहा था उसके समान है। हालांकि, मुझे लगता है कि यह ईएफ की सीमाओं को प्राप्त करने के लिए डेटाबेस को फिर से क्वेरी करने के लिए कुछ हद तक अपर्याप्त है। यही कारण है कि मैं प्रॉक्सी को पुनः प्राप्त करने के लिए अन्य संभावित विकल्पों की खोज कर रहा था। –

1

db.Ent । Ry() इकाई हमेशा आप एक POCO वापस आ जाएगी, और प्रॉक्सी उद्देश्य यह है कि आभासी नेविगेशन गुण के कार्यान्वयन हैंडल नहीं लौटेगा:

var o = db.Entry(myPoco).Entity; // always returns a POCO 

आप आम तौर पर एक POCO के बजाय एक प्रॉक्सी वस्तु मिल जाएगा जब Find() बुला या डेटाबेस संदर्भ के खिलाफ Where()हालांकि, उस संदर्भ में जिसमें किसी ऑब्जेक्ट को डेटाबेस में पहली बार जोड़ा गया है, ये विधियां प्रॉक्सी ऑब्जेक्ट के बजाय POCO को वापस कर देंगी (अप्रत्याशित रूप से?)। आप वास्तव में संदर्भ छोड़ने के लिए और प्रॉक्सी प्राप्त करने के लिए एक नया एक को खोलने के लिए है:

 // create a new POCO object, and connect to it to another object already in the DB 
     MyPoco myPoco = new MyPoco(); 
     myPoco.MyOtherPocoId = myPoco2.MyOtherPocoId; // make reference to existing object 

     using (var db = new MyContext()) 
     { 
      // Add myPoco to database. 
      db.MyPocos.Add(myPoco); 
      db.SaveChanges(); 

      // One would think you get a proxy object here, but you don't: just a POCO 
      var test10 = db.MyPocos.Find(myPoco.Id);      // returns a MyPoco       
      var test11 = db.MyPocos.Where(x => x.Id == myPoco.Id).First(); // returns a MyPoco 
      var test12 = db.Entry(myPoco).Entity;       // returns a MyPoco 

      // ...so, you can't access the referenced properties through virtual navigation properties: 
      MyOtherPoco otherPoco1 = myPoco.Poco2; // returns NULL 
     } 

     // leave the context and build a new one 

     using (var db = new MyContext()) 
     { 
      // Now, the same Find() and Where() methods return a proxy object 
      var test20 = db.MyPocos.Find(myPoco.Id); // returns a proxy object 
      var test21 = db.MyPocos.Where(x => x.Id == myPoco.Id).First(); // returns a proxy object 

      // ...which means the virtual properties can be accessed as expected: 
      MyOtherPoco otherPoco = myPoco.Poco2; // works as expected 

      // Note that db.Entry().Entity still returns a POCO: 
      var test22 = db.Entry(myPoco).Entity; // returns a MyPoco 
     } 

वहाँ संदर्भ में जो वस्तु जोड़ा जाता है बनाने के लिए तुम वापस एक प्रॉक्सी वस्तु देना कुछ जादू मंत्र हो सकता है, लेकिन मैं हेवन इसे पार मत करो।

+0

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

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