【问题标题】:Entity Framework - how to merge child collections? (Best Practices)实体框架 - 如何合并子集合? (最佳实践)
【发布时间】:2014-08-02 07:39:55
【问题描述】:

以下是我的应用程序中的确切场景。

有两个实体:

  • 客户:CustomerId、CustomerName
  • CustomerAddress:AddressId、CustomerId (FK)、Area、City

客户与 CustomerAddress 具有一对多的关系。 一位客户可以拥有多个城市的地址。

当我保存对现有客户的更改时,其基础 CustomerAddress 集合将仅包含一个特定城市的所有地址。

因此,当我在数据库中更新该客户时,它应该 -

  • 为客户添加该城市的所有新地址(即,该地址存在于集合中,但该客户的数据库中不存在)
  • 保留两者通用的地址
  • 删除所有存在于数据库中但不在该城市集合中的地址。

我知道一种方法,其中我可以从数据库中获取客户实体,并且可以通过循环访问地址集合来添加、删除、保留。

但我更感兴趣的是了解实现这一目标的最佳实践。

对此非常感谢有什么想法吗?

【问题讨论】:

    标签: .net linq entity-framework linq-to-entities entity-framework-5


    【解决方案1】:

    这就是我通常做的,就像你说的,循环遍历子导航,这意味着通过一次往返将所有内容加载到内存中,然后在应用程序中处理逻辑,这就是我们使用 ORM 的主要原因。

    // Loads contacts.
    if (customerDb.Id != Guid.Empty)
    {
        context.Entry(customerDb).Collection(c => c.customercontactxrefs).Load();
        foreach (var xref in customerDb.customercontactxrefs)
        {
            context.Entry(xref).Reference(x => x.contact).Load();
        }
    }
    
    // Deletes missing contacts.
    var deletedXrefs = customerDb.customercontactxrefs.Where(xrefDb => !customer.Contacts.Any(contact => xrefDb.ContactId == contact.Id)).ToArray();
    foreach (var xref in deletedXrefs)
    {
        customerDb.customercontactxrefs.Remove(xref);
        context.Set<customercontactxref>().Remove(xref);
    }
    
    // Edits existing contacts.
    foreach (var xrefDb in customerDb.customercontactxrefs)
    {
        var foundContact = customer.Contacts.FirstOrDefault(contact => contact.Id == xrefDb.ContactId);
        if (foundContact != null && xrefDb.contact != null)
        {
            xrefDb.contact.Name = foundContact.Name;
            xrefDb.contact.Phone = foundContact.Phone;
            xrefDb.contact.Mobile = foundContact.Mobile;
            xrefDb.contact.Fax = foundContact.Fax;
            xrefDb.contact.Email = foundContact.Email;
        }
    }
    
    // Adds new contacts.
    var newContacts = customer.Contacts.Where(contact => contact.Id == Guid.Empty).ToArray();
    foreach (var contact in newContacts)
    {
        customerDb.customercontactxrefs.Add(new customercontactxref
        {
            Id = Guid.NewGuid(),
            contact = new contact
            {
                Id = Guid.NewGuid(),
                Name = contact.Name,
                Phone = contact.Phone,
                Mobile = contact.Mobile,
                Fax = contact.Fax,
                Email = contact.Email
            }
        });
    }
    

    或者

    using (RSDContext context = new RSDContext())
    {
        var details = order.OrderDetails;
        order.OrderDetails = null;
    
        context.Entry(order).State = EntityState.Modified;
        foreach (var detail in details)
        {
            if (detail.Id == 0)
            {
                // Adds.
                detail.OrderId = order.Id;
                context.Entry(detail).State = EntityState.Added;
            }
            else if (detail.IsDeleted)
            // Adds new property called 'IsDeleted' 
            //  and add [NotMapped] attribute 
            //  then mark this property as true from the UI for deleted items.
            {
               // Deletes.
               context.Entry(detail).State = EntityState.Deleted;
            }
            else
            {
               // Updates.
               context.Entry(detail).State = EntityState.Modified;
            }
        }
    
        order.OrderDetails = details;
        context.SaveChanges();
    }
    

    【讨论】:

    • 看来这是唯一的选择!感谢分享尤利亚姆
    猜你喜欢
    • 1970-01-01
    • 2010-09-06
    • 2011-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多