2012-11-05 13 views
45

मैं वर्तमान में एंटिटी फ्रेमवर्क के नवीनतम संस्करण का उपयोग कर एक प्रोजेक्ट पर काम कर रहा हूं और मैं एक ऐसे मुद्दे पर आया हूं जिसे मैं हल नहीं कर सकता।इकाई ढांचे, संबंधित वस्तुओं को अद्यतन करने में समस्याएं

जब मौजूदा ऑब्जेक्ट्स को अपडेट करने की बात आती है, तो मैं किसी ऑब्जेक्ट गुणों को ठीक से अपडेट कर सकता हूं, जब तक कि किसी अन्य वर्ग का संदर्भ न हो।

नीचे दिए गए उदाहरण में मैं एक वर्ग फू कहा जाता है, जो विभिन्न गुण संग्रहीत करता है, अन्य वर्गों

public class Foo 
{ 
    public int Id {get; set;} 
    public string Name {get; set;} 
    public SubFoo SubFoo {get; set} 
    public AnotherSubFoo AnotherSubFoo {get; set} 
} 

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

public Foo Edit(Foo newFoo) 
{ 

     var dbFoo = context.Foo 
          .Include(x => x.SubFoo) 
          .Include(x => x.AnotherSubFoo) 
          .Single(c => c.Id == newFoo.Id); 



     var entry = context.Entry<Foo>(dbFoo); 
     entry.OriginalValues.SetValues(dbFoo); 
     entry.CurrentValues.SetValues(newFoo); 

     context.SaveChanges(); 

     return newFoo; 
} 

कोई भी मदद या पॉइंटर्स की सराहना की जाएगी।

अद्यतन: Slauma द्वारा टिप्पणी के आधार पर मैं

public Foo Edit(Foo newFoo) 
{ 

     var dbFoo = context.Foo 
          .Include(x => x.SubFoo) 
          .Include(x => x.AnotherSubFoo) 
          .Single(c => c.Id == newFoo.Id); 



     context.Entry(dbFoo).CurrentValues.SetValues(newFoo); 
     context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo); 

     context.SaveChanges(); 

     return newFoo; 
} 

करने के लिए अपने विधि को संशोधित किया है जब इस चल रहा है, मैं त्रुटि

इकाई प्रकार Collection`1 हिस्सा नहीं है मिल वर्तमान संदर्भ के लिए मॉडल का।

कोशिश करते हैं और इस के आसपास पाने के लिए, मैं संदर्भ के लिए newFoo उपवर्गों संलग्न करने के लिए प्रयास करने के लिए कोड जोड़ा है, लेकिन यह एक त्रुटि के माध्यम से कह रही है कि ObjectManager पहले से ही एक ही

एक वस्तु एक इकाई था ऑब्जेक्टस्टेट प्रबंधक में एक ही कुंजी पहले से मौजूद है। ObjectStateManager, एक ही कुंजी

उत्तर

77

CurrentValues.SetValues केवल अद्यतन करता है अदिश गुण लेकिन कोई संबंधित संस्थाओं के साथ एक से अधिक ऑब्जेक्ट ट्रैक नहीं कर सकते तो आप प्रत्येक संबंधित इकाई के लिए भी ऐसा ही करना चाहिए:

public Foo Edit(Foo newFoo) 
{ 
    var dbFoo = context.Foo 
         .Include(x => x.SubFoo) 
         .Include(x => x.AnotherSubFoo) 
         .Single(c => c.Id == newFoo.Id); 

    context.Entry(dbFoo).CurrentValues.SetValues(newFoo); 
    context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo); 
    context.Entry(dbFoo.AnotherSubFoo).CurrentValues.SetValues(newFoo.AnotherSubFoo); 

    context.SaveChanges(); 

    return newFoo; 
} 

संबंध सकता है पूरी तरह से हटा दिया गया है या बनाया गया है आपको स्पष्ट रूप से उन मामलों को संभालने की भी आवश्यकता है:

public Foo Edit(Foo newFoo) 
{ 
    var dbFoo = context.Foo 
         .Include(x => x.SubFoo) 
         .Include(x => x.AnotherSubFoo) 
         .Single(c => c.Id == newFoo.Id); 

    context.Entry(dbFoo).CurrentValues.SetValues(newFoo); 
    if (dbFoo.SubFoo != null) 
    { 
     if (newFoo.SubFoo != null) 
     { 
      if (dbFoo.SubFoo.Id == newFoo.SubFoo.Id) 
       // no relationship change, only scalar prop. 
       context.Entry(dbFoo.SubFoo).CurrentValues.SetValues(newFoo.SubFoo); 
      else 
      { 
       // Relationship change 
       // Attach assumes that newFoo.SubFoo is an existing entity 
       context.SubFoos.Attach(newFoo.SubFoo); 
       dbFoo.SubFoo = newFoo.SubFoo; 
      } 
     } 
     else // relationship has been removed 
      dbFoo.SubFoo = null; 
    } 
    else 
    { 
     if (newFoo.SubFoo != null) // relationship has been added 
     { 
      // Attach assumes that newFoo.SubFoo is an existing entity 
      context.SubFoos.Attach(newFoo.SubFoo); 
      dbFoo.SubFoo = newFoo.SubFoo; 
     } 
     // else -> old and new SubFoo is null -> nothing to do 
    } 

    // the same logic for AnotherSubFoo ... 

    context.SaveChanges(); 

    return newFoo; 
} 

रिश्ते को और स्केलर गुणों के साथ ही बदल दिया गया है, तो आपको अंततः संलग्न इकाइयों की स्थिति को Modified पर सेट करने की आवश्यकता है।

संपादित

है - अपनी टिप्पणी के अनुसार - Foo.SubFoo वास्तव में एक संग्रह है और न केवल एक संदर्भ आप कुछ इस तरह की जरूरत से संबंधित संस्थाओं को अपडेट करेगा:

public Foo Edit(Foo newFoo) 
{ 
    var dbFoo = context.Foo 
         .Include(x => x.SubFoo) 
         .Include(x => x.AnotherSubFoo) 
         .Single(c => c.Id == newFoo.Id); 

    // Update foo (works only for scalar properties) 
    context.Entry(dbFoo).CurrentValues.SetValues(newFoo); 

    // Delete subFoos from database that are not in the newFoo.SubFoo collection 
    foreach (var dbSubFoo in dbFoo.SubFoo.ToList()) 
     if (!newFoo.SubFoo.Any(s => s.Id == dbSubFoo.Id)) 
      context.SubFoos.Remove(dbSubFoo); 

    foreach (var newSubFoo in newFoo.SubFoo) 
    { 
     var dbSubFoo = dbFoo.SubFoo.SingleOrDefault(s => s.Id == newSubFoo.Id); 
     if (dbSubFoo != null) 
      // Update subFoos that are in the newFoo.SubFoo collection 
      context.Entry(dbSubFoo).CurrentValues.SetValues(newSubFoo); 
     else 
      // Insert subFoos into the database that are not 
      // in the dbFoo.subFoo collection 
      dbFoo.SubFoo.Add(newSubFoo); 
    } 

    // and the same for AnotherSubFoo... 

    db.SaveChanges(); 

    return newFoo; 
} 
+0

धन्यवाद कॉल कर सकते हैं, मैं अपने प्रश्न – Thewads

+0

@Thewads में एक अद्यतन पोस्ट किया है: मैं केवल कल्पना कर सकते हैं कि आप इस "* संग्रह मिलता है ... नहीं है मॉडल का हिस्सा ... * "त्रुटि जब 'Foo.SubFoo' एक * संग्रह * प्रकार है। लेकिन यह केवल एक संदर्भ है 'सार्वजनिक सबफू सबफू {प्राप्त करें; सेट} 'अपने उदाहरण मॉडल में, संग्रह नहीं। क्या यह वास्तव में कोई संग्रह नहीं है? मेरा जवाब आपके वर्तमान मॉडल पर आधारित था जहां 'सबफू' संग्रह नहीं है। – Slauma

+0

क्षमा करें, मुझे एहसास नहीं हुआ कि संग्रह वाले मॉडल में कोई फर्क पड़ता है ... मेरी गलती। मॉडल में मैं इसके साथ काम कर रहा हूं: सार्वजनिक आईसीलेक्शन सबफू {प्राप्त करें; सेट;} – Thewads

3

बस सोचा था कि मैं नीचे दिए गए लिंक को पोस्ट करेंगे क्योंकि इससे मुझे वास्तव में यह समझने में मदद मिली कि संबंधित संस्थाओं को कैसे अपडेट किया जाए।

Updating related data with the entity framework in an asp net mvc application

नोट: मैं तर्क थोड़ा कि UpdateInstructorCourses में दिखाया गया है बदल दिया मेरी आवश्यकताओं के अनुरूप कार्य करते हैं।

0

तुम भी टेबल स्वतंत्र रूप से टिप्पणी के लिए

MyContext db = new MyContext 
// I like using asynchronous calls in my API methods 
var OldFoo = await db.Foo.FindAsync(id); 
var OldAssociateFoo = db.AssociatedFoo; 
var NewFoo = OldFoo; 
var NewAssociatedFoo = OldAssociatedFoo; 

NewFoo.SomeValue = "The Value"; 
NewAssociatedFoo.OtherValue = 20; 

db.Entry(OldFoo).CurrentValues.SetValues(NewFoo); 
db.Entry(OldAssociatedFoo).CurrentValues.SetValues(NewAssociatedFoo); 

await db.SaveChangesAsync(); 
संबंधित मुद्दे