【问题标题】: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();
}