C# 如何在实体框架中更新子列表?

C# 如何在实体框架中更新子列表?,c#,asp.net-mvc,entity-framework,C#,Asp.net Mvc,Entity Framework,这些是模型: public class Contact { public Contact() { Emails = new List<Email>(); } public int Id { get; set; } public string Name { get; set; } public string Surname { get; set; } public string Address { get; s

这些是模型:

public class Contact
{
    public Contact() 
    {
        Emails = new List<Email>(); 
    }
    public int Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public string Address { get; set; }
    public ICollection<Email> Emails { get; set; }

}
 public  class Email
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual int ContactId { get; set; }
}

字符串属性更新得很好,我尝试用同样的方法更新集合,但得到了重复的值。如何更新电子邮件?

适用于儿童实体-最简单的方法是删除所有电子邮件并添加新邮件

var contactFromDb = db.Contacts.Include("Emails").Include("Telephones").Where(x => x.Id == contact.Id).FirstOrDefault();

contactFromDb.Address = contact.Address;
contactFromDb.Name = contact.Name;
contactFromDb.Surname = contact.Surname;
contactFromDb.Telephones = contact.Telephones;
db.Entry(contactFromDb).State = System.Data.EntityState.Modified;
foreach(Email email in contactFromDb.Emails)
{
    db.Entry(email).State = System.Data.EntityState.Deleted;
}
contactFromDb.Emails.AddRange(contact.Emails);
db.SaveChanges();

首先删除已删除的电子邮件:

var contactFromDb = db.Contacts.Include("Emails").Include("Telephones").FirstOrDefault(x => x.Id == updatedContact.Id);
contactFromDb.Address = updatedContact.Address;
contactFromDb.Name = updatedContact.Name;
contactFromDb.Surname = updatedContact.Surname;

// Delete removed emails
var emailsToDelete = (from email in contactFromDb.Emails
                        let item = updatedContact.Emails.SingleOrDefault(i => i.Id == email.Id)
                        where item == null
                        select email).ToList();
if (emailsToDelete.Any())
{
    foreach (var email in emailsToDelete)
    {
        db.Entry(email).State = EntityState.Deleted;
    }
}
foreach (var email in updatedContact.Emails)
{
    // If id of an email is not equal to 0, it's not new email and it should be updated
    if (email.Id > 0)
    {
        var emailInDb = contactFromDb.Emails.Single(e => e.Id == email.Id);
        db.Entry(emailInDb).CurrentValues.SetValues(email);
        db.Entry(emailInDb).State = EntityState.Modified;
    }
}
在更新编辑的电子邮件之后:

var contactFromDb = db.Contacts.Include("Emails").Include("Telephones").FirstOrDefault(x => x.Id == updatedContact.Id);
contactFromDb.Address = updatedContact.Address;
contactFromDb.Name = updatedContact.Name;
contactFromDb.Surname = updatedContact.Surname;

// Delete removed emails
var emailsToDelete = (from email in contactFromDb.Emails
                        let item = updatedContact.Emails.SingleOrDefault(i => i.Id == email.Id)
                        where item == null
                        select email).ToList();
if (emailsToDelete.Any())
{
    foreach (var email in emailsToDelete)
    {
        db.Entry(email).State = EntityState.Deleted;
    }
}
foreach (var email in updatedContact.Emails)
{
    // If id of an email is not equal to 0, it's not new email and it should be updated
    if (email.Id > 0)
    {
        var emailInDb = contactFromDb.Emails.Single(e => e.Id == email.Id);
        db.Entry(emailInDb).CurrentValues.SetValues(email);
        db.Entry(emailInDb).State = EntityState.Modified;
    }
}

最后,通过调用
db.SaveChanges()
将插入Id为
0
的新电子邮件,您可以对
手机重复此循环

使用此通用子项标记子状态,易于使用

笔记:
  • PromatCon:实体对象
  • amList:是要添加或修改的子列表
  • rList:是要删除的子列表

您需要比较集合,哪些是新实体,然后添加它们,哪些是删除的实体,然后删除它们,哪些是现有实体,然后更新它们。在您的电子邮件类中,contactid属性不应是虚拟的。它应该用外键属性标记,并添加带有类contact的虚拟属性。如果email为零,我应该将email添加到数据库中。这似乎有效,但还有更优雅的解决方案吗。我必须对电话和其他收藏品重复这一点。它一点也不优雅。在断开连接的环境中,我认为没有比这更优雅的解决方案了。
public void updatechild<Ety>(ICollection<Ety> amList, ICollection<Ety> rList)
{
    if (amList != null)
    {
        foreach (var obj in amList)
        {
            var x = PromatCon.Entry(obj).GetDatabaseValues();
            if (x == null)
                PromatCon.Entry(obj).State = EntityState.Added;
            else
                PromatCon.Entry(obj).State = EntityState.Modified;
        }
    }

    if (rList != null)
    {
        foreach (var obj in rList.ToList())
            PromatCon.Entry(obj).State = EntityState.Deleted;
    }
}
PromatCon.SaveChanges()