2012-03-01 46 views
12

希望得到一個非常簡單的問題。但我使用的代碼先用一個MVC應用程序,我有一個有一個多對多的關係的類別和服務類型對象:實體框架4不保存我的多對多排

public class Category 
{ 
    public Category() 
    { 
     ServiceTypes = new HashSet<ServiceType>(); 
    } 

    public Guid CategoryId { get; set; } 

    [Required(ErrorMessage = "Name is required")] 
    public string Name { get; set; } 

    public virtual ICollection<ServiceType> ServiceTypes { get; set; } 
} 

數據庫已經正確生成,幷包含一個名爲CategoryServiceTypes一個鏈接表。我的問題是我添加項目到我的ServiceTypes集合並調用保存,雖然沒有錯誤發生,沒有行添加到CategoryServiceTypes。當下面的代碼獲取到的SaveChanges上category.ServiceTypes計數爲1,這樣的東西肯定是集合中:

[HttpPost] 
    public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
    { 
     if (ModelState.IsValid) 
     { 
      // Clear existing ServiceTypes 
      category.ServiceTypes.Clear(); 

      // Add checked ServiceTypes 
      foreach (Guid serviceType in serviceTypeIds) 
      { 
       ServiceType st = db.ServiceTypes.Find(serviceType); 
       category.ServiceTypes.Add(st); 
      } 

      db.Entry(category).State = EntityState.Modified; 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(category); 
    } 

我希望我做的事情很明顯錯在這裏。有任何想法嗎?

謝謝。

編輯:

儘管下面的反應的確是我想我會添加編輯後的方法如下最終版本正確答案:

[HttpPost] 
    public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
    { 
     if (ModelState.IsValid) 
     { 
      // Must set to modified or adding child records does not set to modified 
      db.Entry(category).State = EntityState.Modified; 

      // Force loading of ServiceTypes collection due to lazy loading 
      db.Entry(category).Collection(st => st.ServiceTypes).Load(); 

      // Clear existing ServiceTypes 
      category.ServiceTypes.Clear(); 

      // Set checked ServiceTypes 
      if (serviceTypeIds != null) 
      { 
       foreach (Guid serviceType in serviceTypeIds) 
       { 
        ServiceType st = db.ServiceTypes.Find(serviceType); 
        category.ServiceTypes.Add(st); 
       } 
      } 

      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     return View(category); 
    } 

通知之行力的負荷ServiceTypes集合,這是需要的,因爲延遲加載不包括那些子項目,這意味着清除ServiceTypes集合什麼都不做。

回答

8

嘗試移動,你附加類別上下文中循環的前行:

[HttpPost] 
public ActionResult Edit(Category category, Guid[] serviceTypeIds) 
{ 
    if (ModelState.IsValid) 
    { 
     // Clear existing ServiceTypes 
     category.ServiceTypes.Clear(); 
     db.Entry(category).State = EntityState.Modified; 
     // category attached now, state Modified 

     // Add checked ServiceTypes 
     foreach (Guid serviceType in serviceTypeIds) 
     { 
      ServiceType st = db.ServiceTypes.Find(serviceType); 
      // st attached now, state Unchanged 
      category.ServiceTypes.Add(st); 
      // EF will detect this as a change of category and create SQL 
      // to add rows to the link table when you call SaveChanges 
     } 

     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
    return View(category); 
} 

在你的代碼EF沒有注意到,你所添加的servicetypes因爲你重視的類別當服務類型已經在category.ServiceTypes集合中並且所有服務類型已經附加到狀態Unchanged中的上下文時的上下文。

+0

謝謝Slauma,那正是問題所在。 – Gary 2012-03-04 14:32:57

+0

儘管您的答案現在可以正確地將條目保存到數據庫,但我發現在輸入Edit httppost方法時,即使在編輯響應方法中,category.ServiceTypes計數爲0,但它肯定包含1個保存的ServiceType。任何想法是什麼造成的? – Gary 2012-03-04 14:44:21

+0

@Gary:這將是一個MVC modelbinder問題。對於我來說,如果'category.ServiceTypes'包含某些內容,那看起來並不重要,因爲你所做的第一件事就是無論如何都要清除該列表。重要的僅僅是'Guid [] serviceTypeIds'集合,因爲您使用這些Ids使用'Find'從數據庫加載ServiceType,然後創建與加載的實體的關聯。 – Slauma 2012-03-04 14:50:35