2011-04-17 155 views
2

我在保存對數據庫的更改時遇到問題。SaveChanges()實體框架問題4.1

我更新了模型中的在我的控制器,但是當我保存的SaveChanges使用()我最終在數據庫B.

重複的項目

中的UpdateModel(後)的變化被稱爲我檢查了Bs屬性,這是因爲我期望但是在SaveChanges()被調用後,如果我檢查Bs屬性,我會看到Id完全不同(新的Id和新條目)。

我的班級與此類似:

public class A 
{ 
    [HiddenInput(DisplayValue = false)] 
    public int AId { get; set; } 

    public string Name { get; set; } 

    public virtual ICollection<B> Bs{ get; set; } 
} 

public class B 
{ 
    [HiddenInput(DisplayValue = false)] 
    public int BId { get; set; } 

    public string Name { get; set; } 

    public virtual ICollection<A> As{ get; set; } 
} 

我的控制器是這樣的:

[HttpPost] 
    public ActionResult Edit(A theA) 
    { 
     try 
     { 
      db.Entry(theA).State = EntityState.Modified; 

      foreach (var item in theA.Bs) 
      { 
       db.Entry(item).State = EntityState.Modified; 
      } 

      db.SaveChanges(); 

      return RedirectToAction("Index"); 
     } 
     catch 
     { 
      return View(); 
     } 
    } 

難道我做錯了什麼?

在此先感謝

+0

您的控制器方法對於查看從DB中檢索對象的位置很重要,可以修改它們並調用SaveChanges。 – Slauma 2011-04-17 12:53:40

回答

7

這是常見的行爲。問題在於EF不知道您附加了現有B,因此它會自動插入新記錄。你必須通過調用說,B是現有的EF:

// here add B to the collection in the A and after that call: 
dbContext.Entry<B>(someB).State = EntityState.Unchanged(); 

或通過連接B你它A加至收集之前(我不知道,如果在ASP.NET MVC使用UpdateModel時,這是可能的)。

dbContext.Bs.Attach(someB); 
// now add B to the collection in the A 

另一種可能是先裝入數據庫BA添加加載對象的集合,但它是額外的往返到數據庫。

int id = someB.Id; 
var loadedB = dbCotnext.Bs.Single(b => b.Id == id); 
someA.Bs.Add(loadedB); 
dbContext.As.Add(someA); 
dbContext.SaveChanges(); 

結論:每次你打電話Add如插入,除非你先(將它們添加到插入的父母前 - 第二和第三個例子)附加相關實體的整個對象圖被跟蹤時,或者除非你手動更改狀態的相關實體在添加父代後回到未改變。 (第一個例子)。

+0

謝謝, 我嘗試了第一種方法,但是一旦它被調用,我就會收到以下消息: 「AcceptChanges無法繼續,因爲對象的鍵值與ObjectStateManager中的另一個對象發生衝突,請確保鍵值是唯一的調用AcceptChanges「。 – Raha 2011-04-17 14:50:13

+0

那麼你是如何得到你的B實例的?你是如何創建你的上下文的?上下文是否按每個請求實例化,並且B是否只有每個上下文僅使用一次(單個實例)的給定密鑰? – 2011-04-17 14:54:54

+0

我已將ActionMethod添加到問題中,請問您可以看一下嗎? – Raha 2011-04-17 17:23:48