2012-07-26 28 views
14

navigasyon özelliklerinin değişiklikleri saptamak olmaz Ad ve Adres özelliklerinin her ikisi de atanmış Kişi tipindeki bir nesne. Benim problemim, Kişi nesnesini veritabanından geri alırsam ve Adres özelliğini (ör. Boş Null) değiştirirseniz, e.f. değişikliği tespit etmiyor!Varlık Framework Bir navigasyon özelliğinin değişikliklerin tespit sorun yaşıyorum

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

Neden Değişmeyen entry.Stategeçerli: Benim kod böyle?

Düzenleme: SaveChanges'i çağırırsam, kayıt doğru şekilde kaydedilir (Adres null olur)!

2 Düzenleme: Billy önerildiği gibi yabancı anahtar özellik oluşturduk ve Görsel stüdyoda Kişi nesnesini incelemek eğer nesnenin değerlerini teftiş debugger ile kesmezsen Devlet .. Modifiye edilir Devlet değişmedi!

Düzenleme 3: Kişi nesnesini ctx.People.Include kullanarak yükleme (x => x.Address) .First(); sorunu çözer. Dahil etmeyi önlemek için bir yol var mı ve AddressId yerine Adres özelliğini değiştirmeye devam edilsin mi?

+0

ctx.DetectChanges() öğesini çağırırsanız ne olur? – Maarten

+0

Hiçbir şey. Sonuç aynı! – Mones

cevap

24

İlk: billy tavsiyesi Include kullanmak @ Sen izleyin GEREKİR. "p.Address IS NOT NULL!" ifadeniz yalnızca, hata ayıklayıcısında p.Address izlediğiniz ve bu nedenle hata ayıklayıcısında tembel yüklemeyi tetiklediği için doğrudur, bu nedenle adresin null olarak ayarlanması değişikliği algılanır. Serbest bırakma modunda veya hata ayıklayıcısındaki özellikleri incelemeniz durumunda kodunuz çalışmaz ve hiçbir değişiklik kaydedilmez.

Yani, Edit 3 cevabı:

İkinci Sayısı: var entry = ctx.Entry(p) sadece daha doğrusu yerine ilişki durumu veya varlık devletler ve bir varlık durumunu değişmedi ama döndürür sen bir ilişki silindi.Sen DbContext API ile ilişki durumlarını incelemek olamaz ama sadece ObjectContext API ile:

enter image description here

EF bu ilişki girişini dikkate alacaktır:

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 şimdi tip RelationshipEntry bir giriş gerekir birlikte sen SaveChanges() arayıp ilişkiyi silmek varlık devlet girişleriyle,için veritabanında Person arasında Address yabancı anahtar sütunu oluşturulması gibi.

Düzenleme 2 Hakkında: Bir yabancı anahtar özelliğinin (modelinizde skaler özellik olan) değiştirilmesi, öğenin kendisinde bir değişikliktir, bu durumda varlık durumu Modified olacaktır. Bir yeniden talep veya kullanıcı öğesi/görünüm bırakır önce Benim uygulamada

+0

Vay! teşekkürler gerçekten iyi cevap! –

+0

Güzel cevap, ama bir şüphem var. Belli bir girdinin bu değişiklikten acı çektiğini ve başka bir şey olmadığını nasıl belirleyebilirim, çünkü bu belirli bir içeriğe yönelik bir sorgudur. –

+0

Bunu EF Core'da nasıl yapıyorsunuz, çünkü 'ObjectContext' yok mu? – grokky

5

Adres nav. prop. Kaydetmek zaman sorguda, aksi EF üzerinde değişiklik dikkate almayacaktır: Ayrıca çok sevdiğim Modelinizdeki, yabancı tuşları kullanabilirsiniz

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;} 
} 

... her şeyden

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

Çözümü DetectChanges ile test ettim ama hiçbir şekilde .. değişmedi! Int kullanıyorsam? yabancı anahtar Ben doğru çalışacaktır sanırım çünkü doğrudan bir navigasyon özelliği değil, bir "basit" özellik değerini değiştireceğim. Aslında Kişi nesnesinin Name özelliğini değiştirirsem her şey tamamdır! – Mones

2

, ben hiçbir kaydedilmemiş değişiklikler vardır emin olmak için bazı kontrolleri gerçekleştirin.

Temel olarak şu anda geçerli olan yanıtı kapatıyor, ancak bir uygulama sağlamak istedim ve Context.ChangeTracker.DetectChanges() numaralı telefonu aramadan önce Context.ChangeTracker.DetectChanges() numaralı telefonu aramalıyım. Bunu hata ayıklamak için biraz zaman harcadım, aptal!

_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...