2017-09-21 76 views
0

請不要將其標記爲重複,因爲我已經經歷了類似的問題here,herehere但沒有解決這個問題。附加「XXX.EnquiryLineItem」類型的實體失敗,因爲另一個相同類型的實體已具有相同的主鍵值

完整的錯誤消息引用,

這可以使用「連接」的方法或設置一個實體的狀態時發生「不變」或「修改」,如果圖中的任何實體有衝突的鍵值。這可能是因爲一些實體是新的並且還沒有收到數據庫生成的關鍵值。在這種情況下,使用'Add'方法或'Added'實體狀態來跟蹤圖形,然後根據情況將非新實體的狀態設置爲'Unchanged'或'Modified'。

我有2個相關表Inquiry and EnquiryLineItem,動態添加/編輯。編輯get方法填充並顯示所有綁定的值,包括EnquiryLineItems。使用視圖模型和部分視圖來顯示兩個相關表。編輯發佈方法時發生錯誤。

型號:

public class Enquiry : BaseEntity 
    { 
     public Enquiry() 
     { 
      EnquiryLineItems = new List<EnquiryLineItem>(); 
     } 
     public int ID { get; set; } 
     public DateTime? PreparedDate { get; set; } 
     [StringLength(12)] 
     public string EnquiryNumber { get; set; } 
     public DateTime? ClosingDate { get; set; } 
     public int DivisionID { get; set; } 
     public Division Division { get; set; } 
     public int ClientID { get; set; } 
     public Client Client { get; set; } 

     public virtual ICollection< EnquiryLineItem> EnquiryLineItems { get; set; } 
     public DateTime? RFQSentDate { get; set; } 
    } 
public class EnquiryLineItem : BaseEntity 
    { 
     public int ID { get; set; } 
     [StringLength(80)] 
     public string ItemDesc { get; set; } 
     [Range(1, int.MaxValue, ErrorMessage = "Please enter valid Quantity")] 
     public int Quantity { get; set; } 
     public int EnquiryID { get; set; } 
     public Enquiry Enquiry { get; set; } 
     public int? ManufacturerID { get; set; } 
     public Manufacturer Manufacturer { get; set; } 
    } 

控制器方法:

[HttpPost] 
     [ValidateAntiForgeryToken] 
     public ActionResult Edit(EnquiryVM enquiryVM) 
     { 
      var ID = enquiryVM.ID; 
      var enquiry = new Enquiry(); 
      enquiry.EnquiryNumber = enquiryVM.EnquiryNumber; 
      enquiry.ClosingDate = enquiryVM.ClosingDate; 
      enquiry.RFQSentDate = enquiryVM.RFQSentDate; 
      enquiry.ClientID = enquiryVM.ClientID; 
      enquiry.DivisionID = enquiryVM.DivisionID; 

      if (ModelState.IsValid) 
      { 
       foreach (var lineItemVm in enquiryVM.LineItems) 
       { 

         EnquiryLineItem enquiryLineItem = new EnquiryLineItem(); 
         enquiryLineItem.ItemDesc = lineItemVm.ItemDesc; 
         enquiryLineItem.Quantity = lineItemVm.Quantity; 
         enquiryLineItem.ManufacturerID = lineItemVm.ManufacturerId; 
         enquiry.EnquiryLineItems.Add(enquiryLineItem); 

       } 

       db.Entry(enquiry).State = EntityState.Modified; 

       db.SaveChanges(); 


       return RedirectToAction("Index"); 
      } 
      //ConfigureViewModel(); 
      return View(enquiryVM); 
     } 

上下文:

public override int SaveChanges() 
     { 
      foreach (var entry in ChangeTracker.Entries()) 
      { 
       var entity = entry.Entity; 
       if (entry.State == EntityState.Added) 
       { 
        entry.Property("AddedDate").CurrentValue = DateTime.Now; 

        entry.Property("AddedBy").CurrentValue = HttpContext.Current.User.Identity.Name; 
        entry.Property("AddedById").CurrentValue = HttpContext.Current.User.Identity.GetUserId(); 

       } 
       else if (entry.State == EntityState.Modified) 
       { 
        entry.Property("AddedDate").IsModified = false; 
        entry.Property("AddedBy").IsModified = false; 
        entry.Property("AddedById").IsModified = false; 
        entry.Property("ModifiedDate").CurrentValue = DateTime.Now; 
        entry.Property("ModifiedBy").CurrentValue = HttpContext.Current.User.Identity.Name; 
        entry.Property("ModifiedById").CurrentValue = HttpContext.Current.User.Identity.GetUserId(); 

       } 
      } 
      return base.SaveChanges(); 
     } 

在編輯檢視有一個添加/編輯/局部視圖刪除了LineItem在詢查看自己。因此EnquiryModel Editing將具有可以編輯的LineItems,甚至可以添加/刪除。

注意: 如果我添加db.Set<Enquiry>().AddOrUpdate(enquiry);然後它添加查詢和LineItems作爲新的插入而不是編輯。

使用MVC 5和EF6 Codefirst方法。 對此感謝一些幫助。提前致謝。

+1

您創建一個新的'Enquiry'的對象,而不是設置它的'ID'財產,而不是將其連接到數據庫上下文(但你將其標記爲'EntityState。 Modified')。你應該做的是根據視圖模型'ID'從數據庫獲取現有的'Enquiry',然後根據視圖模型更新其屬性。 –

+0

您還應該在執行其他任何操作之前檢查'ModelState'是否有效。 –

回答

1

你創建一個新的Enquiry數據模型中沒有設置其ID屬性或將其附加到上下文。您應該根據視圖模型的ID獲取現有數據模型,然後更新其屬性並保存。

更改控制器代碼

[HttpPost] 
[ValidateAntiForgeryToken] 
public ActionResult Edit(EnquiryVM enquiryVM) 
{ 
    if(!ModelState.IsValid) 
    { 
     ConfigureViewModel(enquiryVM); 
     return View(enquiryVM) 
    } 
    // Get the data model 
    var enquiry = db.Enquiries.FirstOrDefault(x => x.ID == enquiryVM.ID.Value); 
    // update properties of enquiry from the enquiryVM 
    enquiry.EnquiryNumber = enquiryVM.EnquiryNumber; 
    enquiry.ClosingDate = enquiryVM.ClosingDate; 
    .... 
    foreach (var lineItemVm in enquiryVM.LineItems) 
    { 
     if (lineItemVm.ID.HasValue) 
     { 
      var lineItem = enquiry.LineItems.FirstOrDefault(x => x.ID == lineItemVm.ID.Value); 
      // update properties of lineItem from lineItemVm (but dont add it to the collection) 
      lineItem.ItemDesc = lineItemVm.ItemDesc; 
      lineItem.Quantity = lineItemVm.Quantity; 
      lineItem.ManufacturerID = lineItemVm.ManufacturerId; 
     } 
     else 
     { 
      // create a new EnquiryLineItem data model based on lineItemVm and add it to the data models `LineItems` collection 
      EnquiryLineItem enquiryLineItem = new EnquiryLineItem(); 
      enquiryLineItem.EnquiryID = enquiryVM.ID.Value; // modify this 
      enquiryLineItem.ItemDesc = lineItemVm.ItemDesc; 
      enquiryLineItem.Quantity = lineItemVm.Quantity; 
      enquiryLineItem.ManufacturerID = lineItemVm.ManufacturerId; 
      enquiry.EnquiryLineItems.Add(enquiryLineItem); 
     } 
     db.Entry(enquiry).State = EntityState.Modified; 
     db.SaveChanges(); 
     return RedirectToAction("Index"); 
    } 
} 
相關問題