【问题标题】:Entity Framework inserting new rows instead of updating them实体框架插入新行而不是更新它们
【发布时间】:2014-12-30 19:12:21
【问题描述】:

我在将数据更新到数据库时遇到问题。当我想更新数据时,Entity Framework 会向可以包含多行的表(具有外键的表)添加新行。

数据库模型:

当我更新电话/联系人或标签实体时,实体框架会自动添加新行而不是更新它

这是我使用的代码:

public string UpdateContact(Contact contact)
{
    if (contact != null)
    {

        int id = Convert.ToInt32(contact.id);
        Contact Updatecontact = db.Contacts.Where(a => a.id == id).FirstOrDefault();
        Updatecontact.firstname = contact.firstname;
        Updatecontact.lastname = contact.lastname;
        Updatecontact.address = contact.address;
        Updatecontact.bookmarked = contact.bookmarked;
        Updatecontact.city = contact.city;
        Updatecontact.notes = contact.notes;
        Updatecontact.Emails1 = contact.Emails1;
        Updatecontact.Phones1 = contact.Phones1;
        Updatecontact.Tags1 = contact.Tags1;
        db.SaveChanges();
        return "Contact Updated";

    }
    else
    {
        return "Invalid Record";
    }
}

编辑:

这是 EF 型号代码:

联系方式:

public partial class Contact
{
    public Contact()
    {
        this.Emails1 = new HashSet<Email>();
        this.Phones1 = new HashSet<Phone>();
        this.Tags1 = new HashSet<Tag>();
    }

    public int id { get; set; }
    public string firstname { get; set; }
    public string lastname { get; set; }
    public string address { get; set; }
    public string city { get; set; }
    public Nullable<byte> bookmarked { get; set; }
    public string notes { get; set; }

    public virtual ICollection<Email> Emails1 { get; set; }
    public virtual ICollection<Phone> Phones1 { get; set; }
    public virtual ICollection<Tag> Tags1 { get; set; }
}

电子邮件/标签和电话具有相同的型号(价值不同的名称)

public partial class Email
{
        public int id { get; set; }
        public int id_contact { get; set; }
        public string email1 { get; set; }

        public virtual Contact Contact1 { get; set; }
}

【问题讨论】:

  • 关系是一对多还是一对一?
  • 一对多是关系@beauXjames
  • 好吧,您并没有真正加载 Emails1/Phones1/Tags1 对象,而是将它们设置为作为参数传入的它们的新实例......因为你可以有很多,那么它只是假设你想用新的 id 创建新的

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


【解决方案1】:

更新属性而不是设置新对象。

  Updatecontact.Emails1.email1 = contact.Emails1.email1;
  Updatecontact.Phones1.number = contact.Phones1.number;
  Updatecontact.Tags1.tag1 = contact.Tags1.tag1;

编辑:您的联系人模型似乎有电子邮件、电话和标签的列表。如果是这样,那么简单的分配将不起作用。相反,当从客户端发送时,您必须一一查找并更新:

 foreach ( var email in contact.Emails1 )
 {
     // first make sure the object is retrieved from the database 
     var updateemail = Updatecontact.Emails1.FirstOrDefault( e => e.id == email.id );
     // then update its properties
     updateemail.email1 = email.email1;
 }

 // do the same for phones and tags

【讨论】:

  • 问题是我联系了。Emails1.email1 没有定义。我无法访问它。我需要更新我的模型吗?
  • 未定义意味着编译时问题或 NullReferenceException?
  • 我认为 OP 意味着它们是集合,而不仅仅是单个属性。
  • 我更新了我的帖子@WiktorZychla。当我创建模型时,我使用 ADO.NET EF 模型自动生成它。
  • @IronMan84:看来是这样,我会在回答中解决这个问题。
【解决方案2】:

这样做是因为您将不同的 HashSet 值设置为完全不同的集合的值,即从您在该方法中调用的 contact 的值。为了让您正确进行更新,您将不得不遍历电子邮件、电话和标签,以检查是否需要在您尝试更新的实际对象上添加/更新/删除这些内容。

【讨论】:

  • 如果我更新联系人表中的数据并将外键修改为更新时 CASCADE 删除怎么办?之后我只是将数据插入到标签/电子邮件和电话等表格中?
【解决方案3】:

首先,如果你已经通过参数接收了联系人,为什么还要搜索呢?这让人认为您创建一个新记录是因为您处于不同的上下文中,如果是这样,那么它会创建一个新记录,因为您在 2 个不同的上下文中有 2 个不同的对象。

尝试在同一上下文中仅使用一个对象进行更新,EF 应自行标记要修改的对象,如果没有,则尝试在保存之前确保您的对象具有 EntityState.Modified。

【讨论】:

  • 所以我只需将联系人保存到数据库并运行 db.SaveChanges() ?
  • 是的,EF 会处理的
猜你喜欢
  • 1970-01-01
  • 2017-02-01
  • 2020-05-30
  • 1970-01-01
  • 1970-01-01
  • 2020-03-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多