2012-03-14 63 views
1

(首先抱歉的英語不好)實體框架4.3.1的DbContext添加對象與現有引用的對象

我是新來的實體框架和我做測試的一點點。讓我們假設我有2個對象是POCO對象。人員和地址。

我的場景是,我想添加一個新的人到DbContext有一個已經存在的對象的引用。兩個實體之間的連接是一個Many:Many關係。

using (var t = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     testaddress = (from c in t.Adresses 
         select c).ToList().FirstOrDefault(); 
} 

var newPerson = new Person(); 
newPerson.Name = "Henry"; 
newPerson.Adresses.Add(testaddress); 

using (var k = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     k.Persons.Add(newPerson); 
     k.SaveChanges(); 
} 

我現在做的問題是,一旦人是增加了一個額外的地址(具有相同的價值觀,但一個新的密鑰)將被創建。我如何將現有的引用添加到新的對象而不是創建一個新的對象?

+0

最簡單的辦法是重寫的SaveChanges,通過已保存的所有實體和那些(ID> 0),將其設置爲「不變」,或者,如果你想堅持最終取得了修改,「修改時間」 – UrbanEsc 2012-03-14 17:36:48

回答

2

整個操作使用一個上下文:

using (var t = new Tww.SV.Models.Model.Portal.SVPortalEntities()) 
{ 
     testaddress = (from c in t.Adresses 
         select c).ToList().FirstOrDefault(); 
     var newPerson = new Person(); 
     newPerson.Name = "Henry"; 
     newPerson.Adresses.Add(testaddress); 
     k.Persons.Add(newPerson); 
     k.SaveChanges(); 
} 

如果你不能做那麼,您需要通過ObjectStateManager或類似的方法手動更改新上下文中現有地址的狀態。

+0

迭代最後我使用了這些自我追蹤對象 – KroaX 2012-03-16 13:19:36

1

首先,您是否需要在數據上下文的兩個單獨實例中執行此操作?我假設你這樣做,並且你只是提供了一個簡化的例子,但是如果沒有,那麼在整個代碼中使用相同的上下文實例將解決你的問題。

但是,這是一個常見問題,特別是在跨WCF等服務使用EF類時。我發現的最佳解決方案是在保存傳入的新對象之前「修復」新傳入的對象。我會成爲第一個管理員,我覺得這個「醜陋」,但我也沒有找到任何更好的選項,實際上一直工作。我通常把參考重新關聯的代碼放到一個方法,在我的實體類的另一部分類段:

public void FixUp(EntityContext c) 
{ 
    for (int i = 0; i < this.Addresses.Count; i++) 
    { 
    var existing = c.Addresses.SingleOrDefault(a => a.Id = this.Addresses[i].Id); 
    if (existing != null) 
    { 
     this.Addresses[i] = existing; 
    } 
    } 
} 

using (var k = new EntityContext()) 
{ 
    newPerson.FixUp(k); 
    k.Persons.Add(newPerson); 
    k.SaveChanges(); 
} 
0

解釋爲什麼會發生這種情況:您正在創建兩個DbContext。首先,您檢索一個地址對象。然後,在任何Context範圍之外(請參閱使用),您正在創建一個新的脫節人。它不屬於你的兩種情況之一。接下來發生的事情是,您創建一個新的上下文並添加您的對象到其中。

此背景下,現在不知道你的新(這是「超出範圍」,或獨立),也不是你的ADRESS(這是從另一個方面)。這兩個實體都將被添加並標記爲ChangeTracker,已添加

你有多個解決方案:

  • 首先,只能使用一個上下文檢索您ADRESS,在創建添加它。你需要稍微改變一下你的代碼,如果你正在開發基於服務的場景,它可能不適合你。

  • 第二,如果你有沒有改變這個代碼的機會,你需要連接分離對象,就像你在你的代碼片段做,你可能希望覆蓋的SaveChanges你的上下文類,並通過實體迭代在ChangeTracker。那些已保存的(Id> 0)可能會設置爲「未更改」,或者如果您想保留最終進行的更改,請使用「修改」。這感覺很難看,但它應該工作。