2012-07-26 29 views
14

मैं एक नेविगेशन संपत्ति के परिवर्तन का पता लगाने में परेशानी आ रही के परिवर्तन का पता लगाने नहीं होगा:इकाई की रूपरेखा नेविगेशन गुण

public class Person 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public virtual Address Address { get; set; } 
} 

public class Address 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 
} 

मैं बनाया है और सहेज कर रखा है:

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

using (var ctx = new EFContext()) 
{ 
    Person p = ctx.People.First(); 
    //p.Address IS NOT NULL! 
    p.Address = null; 
    var entry = ctx.Entry(p); 
} 

entry.Stateअपरिवर्तित क्यों है: मेरे कोड है?

संपादित करें: अगर मैं SaveChanges को कॉल करता हूं, तो रिकॉर्ड सही ढंग से सहेजा जाता है (पता शून्य हो जाता है)!

संपादित करें 2: मैं विदेशी कुंजी संपत्ति बना लिया है के रूप में बिली सुझाव दिया और अगर मैं दृश्य स्टूडियो में व्यक्ति वस्तु का निरीक्षण राज्य संशोधित है .. अगर मैं वस्तु के मूल्यों का निरीक्षण डीबगर के साथ बंद नहीं करते राज्य अपरिवर्तित है!

संपादित करें 3: ctx.People का उपयोग करके व्यक्ति वस्तु लोड हो रहा है। शामिल करें (x => x.Address)। सबसे पहले(); समस्या हल करता है। क्या कॉल करने से बचने का कोई तरीका है और पता आईडी के बजाय पता संपत्ति को संशोधित करना जारी रखें?

+0

यदि आप ctx.DetectChanges() को कॉल करते हैं तो क्या होता है? – Maarten

+0

कुछ भी नहीं। नतीजा वही है!! – Mones

उत्तर

24

पहले: @ बिली की सलाह Include उपयोग करने के लिए आप का पालन करना आवश्यक है। आपकी टिप्पणी "पी। एड्रेस न्यूल नहीं है!" केवल सत्य है क्योंकि आप डीबगर में p.Address देख रहे हैं और इस प्रकार डीबगर में आलसी लोडिंग ट्रिगर कर रहे हैं, इसलिए पते को null पर सेट करने का परिवर्तन पता चला है। रिलीज मोड में या जब आप डीबगर में गुणों का निरीक्षण नहीं करते हैं तो आपका कोड काम नहीं करेगा और कोई भी बदलाव सहेजा नहीं जाएगा।

तो, अपने संपादित 3 का जवाब है: नहीं

दूसरा: var entry = ctx.Entry(p) केवल रिटर्न इकाई कहा गया है और आप एक इकाई राज्य परिवर्तन नहीं किया लेकिन इसके बजाय एक संबंध राज्य, या अधिक सटीक आप हटाया गया एक रिश्ते।आप DbContext एपीआई के साथ संबंध राज्यों का निरीक्षण नहीं कर सकते हैं, लेकिन केवल ObjectContext एपीआई के साथ:

enter image description here

एफई इस रिश्ते प्रवेश पर विचार करेंगे:

Person p = ctx.People.Include(x => x.Address).First(); 
p.Address = null; 
var objCtx = ((IObjectContextAdapter)ctx).ObjectContext; 
var objentr = objCtx.ObjectStateManager.GetObjectStateEntries(EntityState.Deleted); 

objentr अब प्रकार RelationshipEntry की एक प्रवेश करना होगा SaveChanges() पर कॉल करते समय इकाई स्थिति प्रविष्टियों के साथ-साथ संबंधों को हटाएं, यानी AddressPerson केपर डेटाबेस में विदेशी कुंजी कॉलम सेट करें।

संपादन के बारे में 2: एक विदेशी कुंजी संपत्ति (जो आपके मॉडल में एक स्केलर संपत्ति है) बदलना इकाई का एक परिवर्तन है, इसलिए इकाई स्थिति Modified इस मामले में होगी।

+0

वाह! धन्यवाद वास्तव में अच्छा जवाब! –

+0

अच्छा जवाब, लेकिन मुझे शक है। मैं कैसे पहचानूं कि एक विशिष्ट प्रविष्टि को इस परिवर्तन का सामना करना पड़ा और अन्य नहीं, क्योंकि यह विशिष्ट संदर्भ के लिए एक प्रश्न है। –

+0

ईएफ कोर में आप इसे कैसे करते हैं, क्योंकि 'ऑब्जेक्ट कॉन्टेक्स्ट' नहीं है? – grokky

5

आपको पता नौवहन शामिल करने की आवश्यकता है। सहारा। आपकी क्वेरी में, अन्यथा एफई जब आप सहेजने उसमें परिवर्तन पर विचार नहीं करेंगे:

using (var ctx = new EFContext()) 
{ 
    Person p = ctx.People.Include(x => x.Address).First(); 
    //p.Address IS NOT NULL! 
    p.Address = null; 
    var entry = ctx.Entry(p); 
} 

आप भी अपने मॉडल है, जो मैं बहुत पसंद में विदेशी कुंजी का उपयोग कर सकते हैं:

public class Person 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public virtual Address Address { get; set; } 

    public int? AddressId {get; set;} 
} 

... सब से

using (var ctx = new EFContext()) 
{ 
    Person p = ctx.People.First(); 
    p.AddressId = null; 
    var entry = ctx.Entry(p); 
} 
+0

मैंने डिटेक्ट चेंज के साथ समाधान का परीक्षण किया है लेकिन कोई रास्ता नहीं .. अभी भी अपरिवर्तित राज्य मिला है! अगर मैं int का उपयोग करता हूं? विदेशी कुंजी मुझे लगता है कि यह सही काम करेगा क्योंकि मैं एक "सरल" संपत्ति का मूल्य बदलने जा रहा हूं, न कि नेविगेशन संपत्ति सीधे। असल में अगर मैं व्यक्ति वस्तु की नाम संपत्ति बदलता हूं तो सब कुछ ठीक है! – Mones

2

मेरे आवेदन में, एक रीलोड से अनुरोध करने से पहले या उपयोगकर्ता आइटम/दृश्य छोड़ देता है, मैं यह सुनिश्चित करने के लिए कुछ चेक करता हूं कि कोई सहेजे गए परिवर्तन नहीं हैं।

यह मूल रूप से वर्तमान में स्वीकृत उत्तर को बंद कर रहा है, लेकिन मैं एक कार्यान्वयन प्रदान करना चाहता था और से पहले Context.ChangeTracker.DetectChanges() पर कॉल करना चाहिए ताकि आप संबंधों में बदलाव कर सकें! मैंने इसे बेवकूफ़ बना दिया, मूर्खतापूर्ण!

_EagleContext.ChangeTracker.DetectChanges(); 

var objectContext = ((IObjectContextAdapter)_EagleContext).ObjectContext; 
var changedEntities = objectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified); 

if (_EagleContext.ChangeTracker.Entries().Any(e => e.State == EntityState.Modified) 
    || changedEntities.Count() != 0) 
{ 
    var dialogResult = MessageBox.Show("There are changes to save, are you sure you want to reload?", "Warning", MessageBoxButton.YesNo); 
    if (dialogResult == MessageBoxResult.No) 
    { 
     return; 
    } 
} 

// Continue with reloading... 
संबंधित मुद्दे