2011-08-16 80 views
1

EF 4.1參考類型屬性,POCO:我關掉AutoDetectChangesConfiguration.AutoDetectChangesEnabled =假)來加快數據更新。然後我運行添加附加與實體狀態更改爲EntityState.Modified。所有這些都會導致對數據庫中未更新的其他對象的引用。但是,所有標量屬性都已成功更新。EF 4.1,POCO:不更新的情況下,AutoDetectChanges =假

事件探查器顯示EF爲每個標量屬性生成SQL更新操作,但不是引用類型,儘管我真的改變了它在我的代碼中的值。這個問題在我的模型中爲每種類型的實體重現。

添加操作或附加EntityState.Added都工作得不錯。如果我再次打開AutoDetectChanges,則對於更新的記錄,一切正常。

請幫我弄清楚什麼是錯的。我無法找到有關EF檢測變更的完整文檔。

UPDATE

有人問我把一些代碼示例重現該問題。域名:

public class Client 
{ 
    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 virtual string City { get; set; } 
} 

的DataContext:

public class DataContext : DbContext 
{ 

    public DbSet<Client> Clients { get; set; } 
    public DbSet<Address> Address { get; set; } 
    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
    base.OnModelCreating(modelBuilder); 
     modelBuilder.Entity<Client>().HasOptional(c => c.Address); 
    } 
} 

添加一條記錄克林特表和一個地址。點客戶到地址。然後運行下面的代碼:

using (var cntx = new DataContext()) 
{ 
    cntx.Configuration.AutoDetectChangesEnabled = false; // Reason of problem 
    var client = cntx.Clients.First(); 
    client.Name = "Anna"; // This property will be updated 
    client.Address = null; // This property will not be updated 
    cntx.Clients.Attach(client); 
    cntx.Entry(client).State = EntityState.Modified; 
    cntx.SaveChanges(); 
} 

此代碼生成SQL腳本是這樣的:

update [dbo].[Clients] set [Name] = 'Anna' 
where ([Id] = 1) 

設置AutoDetectChangesEnabled爲true,並再次運行代碼,這個時候一切都好:

update [dbo].[Clients] 
set [Name] = 'Anna', [Address_Id] = null 
where (([Id] = 1) and [Address_Id]=1) 

注意,如果將Address的值從特定值更改爲null或返回特定值或將具體值更改爲其他具體值,則無關緊要,但AutoDe時不會跟蹤任何更改tectChanges =假。看起來像EF錯誤。

+0

顯示一些可以重現您的問題的代碼。 –

回答

2

好吧,我發現了設置,即使AutoDetectChangesEnabled =虛假工程參考屬性值的方式:

cntx.Entry(client).Reference(c => c.Address).CurrentValue = null; 

但是我絕對不喜歡它。 1)代碼看起來很醜陋; 2)你必須有訪問上下文才能使其工作,這不是我的情況,我想這個屬性設置在只有DbContext訪問權限的存儲庫之外。是否有任何其他更簡單的方法讓EF知道屬性值已更改?

更新:好的,我發現更簡單的解決方法:只需運行cntx.ChangeTracker。在運行cntx.SaveChanges()之前執行DetectChanges()。它可以幫助EF生成正確的SQL更新腳本

+0

您更新的答案正是我所提供的,btw ... –

+0

這就是爲什麼我upvoted你的答案。仍然不明白爲什麼EF如此怪異的方式工作。關閉AutoDetectChangesEnabled可使EF持續跟蹤標量類型屬性的更改,但不會爲引用類型進行跟蹤。它不應該工作或爲所有的財產工作,否則它是一團糟,導致混亂。我認爲它是微軟的錯誤。 – YMC

2
+0

這不是全面的文檔,它留下了很多有關此檢測更改實現的問題,例如何時使用快照和何時使用代理檢測方法,以及如何在EF跳過引用屬性更新時解釋此行爲。 – YMC