附加“XXX.EnquiryLineItem”类型的实体失败,因为同一类型的另一个实体已具有相同的主键值

时间:2017-09-21 18:48:31

标签: c# asp.net-mvc entity-framework

请不要将其标记为重复,因为我已经完成了类似的问题hereherehere,但没有解决问题。

引用完整的错误消息,

  

如果图中的任何实体具有冲突的键值,则使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图表,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。

我有2个相关的表Inquiry和EnquiryLineItem,动态添加/编辑。 edit get方法填充并显示绑定的所有值,包括EnquiryLineItems。使用viewmodel和partial视图显示相关表。编辑帖子方法时出错。

模特:

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();
        }

在“编辑”视图中,有一个部分视图,用于在“查询视图”本身中添加/编辑/删除LineItems。所以EnquiryModel Editing将有LineItems,可以编辑,甚至添加/删除。

注意: 如果我添加db.Set<Enquiry>().AddOrUpdate(enquiry);,则将其添加查询和LineItems作为新插入而不是编辑。

使用MVC 5和EF6 Codefirst方法。 感谢一些帮助。提前致谢。

1 个答案:

答案 0 :(得分: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");
    }
}