2013-07-09 136 views
3

我有Apple和Orange表之間的多對多關係。實體框架5.0代碼首先多對多更新

public class Apple 
{ 
    [Key] 
    public int AppleID { get; set; } 

    [Required] 
    public string AppleName { get; set; } 

    [NotMapped] 
    public int[] SelectedOranges { get; set; } 

    public virtual ICollection<Orange> Oranges { get; set; } 

} 

public class Orange 
{ 

    [Key] 
    public int OrangeID { get; set; } 
    public String OrangeName { get; set; } 
    public virtual ICollection<Apple> Apples { get; set; } 
} 

在數據上下文類,OnModelCreating方法被重寫像下面

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     base.OnModelCreating(modelBuilder); 

     //---------------------------------------------------------------- 
     //Creating a Association (Intermediate Table) which 
     //will hold M2M relations from Student to Course. 
     //---------------------------------------------------------------- 

     modelBuilder.Entity<Apple>() 
      .HasMany(c => c.Oranges) 
      .WithMany(t => t.Apples); 
    } 

當我從控制器保存編輯後的值在我的ASP.NET MVC應用程序,我得到以下異常:

保存不爲其關係提供外鍵屬性的實體時發生錯誤。 EntityEntries屬性將返回null,因爲單個實體不能被識別爲異常的來源。通過在您的實體類型中公開外鍵屬性,可以更輕鬆地處理保存時的異常。有關詳細信息,請參閱InnerException。

內部異常是:

PRIMARY KEY約束 'PK_dbo.AppleOranges' 的相關規定。無法在對象'dbo.AppleOranges'中插入重複鍵。重複的鍵值是(1,3)。\ r \ n語句已被終止。

任何想法?

AppleController:

// 
    // GET: /Apple/Edit/5 

    public ActionResult Edit(int id = 0) 
    { 

     Apple Apple = db.Apples.Find(id); 
     if (Apple == null) 
     { 
      return HttpNotFound(); 
     } 
     var selectedvalues = new List<Orange>(); 
     Apple.SelectedOranges = new int[Apple.Oranges.Count]; 
     int j=0; 
     foreach (var i in Apple.Oranges) 
     { 
      selectedvalues.Add(i); 
      Apple.SelectedOranges[j++] = db.Oranges.ToList().IndexOf(i)+1; 
     } 
     ViewBag.OrangesList = new MultiSelectList(db.Oranges, "OrangeID", "OrangeName", selectedvalues); 
     return View(Apple); 
    } 

    // 
    // POST: /Apple/Edit/5 

    [HttpPost] 
    public ActionResult Edit(Apple Apple) 
    { 
     if (ModelState.IsValid) 
     { 
      db.Entry(Apple).State = EntityState.Modified; 
      foreach (var i in Apple.SelectedOranges) 
      { 
       if (Apple.Oranges == null) 
        Apple.Oranges = new List<Orange>(); 
       Apple.Oranges.Add(db.Oranges.Find(i)); 
      } 
      db.SaveChanges(); 
      return RedirectToAction("Index"); 
     } 
     ViewBag.OrangesList = new MultiSelectList(db.Oranges, "OrangeID", "OrangeName", Apple.SelectedOranges); 
     return View(Apple); 
    } 

蘋果編輯觀點:

@using (Html.BeginForm()) { 
@Html.ValidationSummary(true) 

<fieldset> 
    <legend>Apple</legend> 

    @Html.HiddenFor(model => model.AppleID) 

    <div class="editor-label"> 
     @Html.LabelFor(model => model.AppleName) 
    </div> 
    <div class="editor-field"> 
     @Html.EditorFor(model => model.AppleName) 
     @Html.ValidationMessageFor(model => model.AppleName) 
    </div> 


    <div class="editor-label"> 
     @Html.LabelFor(model => model.Oranges) 
    </div> 
    <div class="editor-field"> 
     @Html.ListBoxFor(m=>m.SelectedOranges,(MultiSelectList)ViewBag.OrangesList) 
     @Html.ValidationMessageFor(model => model.Oranges) 
    </div> 

    <p> 
     <input type="submit" value="Save" /> 
    </p> 
</fieldset> 

}

+1

FYI刪除代碼,EF將已經推斷出許多對許多當你有兩個'ICollection的'性質指向對方。 –

+0

是的,我正在使用codefirst方法使EF推斷出多對多,正如你所說的! – Seenu

+0

我似乎沒有問題:https://gist.github.com/bchristie/5957381 –

回答

8

必須加載​​首先,將項目添加到它。如果集合已加載,EF的更改跟蹤器將知道哪些關聯是新建的,哪些已存在,並且只有新的關聯將被保存。

您可以通過

db.Entry(Apple).Collection(a => a.Oranges).Load() 

加載集合,你可以

if (Apple.Oranges == null) 
    Apple.Oranges = new List<Orange>();