EF7 如何处理嵌套实体的更新操作
Posted
技术标签:
【中文标题】EF7 如何处理嵌套实体的更新操作【英文标题】:EF7 How to handle the update operation for nested entities 【发布时间】:2016-03-05 21:48:46 【问题描述】:我正在尝试找出更新实体及其所有子实体时的最佳做法。例如;我有一个“雇主”更新服务,它将更新雇主实体和雇主的“地址”实体以及每个“地址”的“电话”实体。用户可以向现有雇主添加新地址,也可以更新当前地址或删除一些地址,每个地址的电话也是如此。你能帮我写出处理这种情况的理想代码吗?
我正在使用 EF7 rc1,并使用 Automapper 将 Dto 映射到我的服务中的实体。
public partial class Employer
public int EmployerId get; set;
public int Name get; set;
[InverseProperty("Employer")]
public virtual ICollection<Address> Address get; set;
public partial class Address
public int AddressId get; set;
public int Address1 get; set;
public int City get; set;
[ForeignKey("EmployerId")]
[InverseProperty("Address")]
public virtual Employer Employer get; set;
[InverseProperty("Address")]
public virtual ICollection<Phone> Phone get; set;
public partial class Phone
public int PhoneId get; set;
public string Number get; set;
[ForeignKey("AddressId")]
[InverseProperty("Phone")]
public virtual Address Address get; set;
我的服务方式;
public async Task<IServiceResult> Update(EmployerDto employer)
var employerDbEntity = await _db.Employer
.Include(a=>a.Address).ThenInclude(p=>p.Phone)
.SingleOrDefaultAsync (a=>a.EmployerId == employer.EmployerId);
//How to handle the update operation for children?
var entity = Mapper.Map<Employer>(employer);
HandleChildren(employerDbEntity,entity);
await _db.SaveChangesAsync();
...
...
private void HandleChildren(Employer employerDbEntity,Employer entity)
//Delete
foreach (var existing in employerDbEntity.Address.ToList())
if (!entity.Address.Any(a => a.AddressId == existing.AddressId))
employerDbEntity.Address.Remove(existing);
//Update or Insert
foreach (var address in entity.Address)
var existing = employerDbEntity.Address.SingleOrDefault(a =>a.AddressId == address.AddressId);
//Insert
if (existing == null)
employerDbEntity.Address.Add(address);
//Update
else
Mapper.Map(address, existing);
【问题讨论】:
【参考方案1】:这个例子看起来是处理子集合的好方法。每个集合都必须手动检查执行的操作。 (使用泛型听起来不错,但总是以某种方式反击。通常是性能。)
考虑到这一点,这里有一些建议:
将子集合处理移动到单独的方法/服务中。 如果查询现有实体,请在一次查询中检索整个集合,然后在内存中迭代结果。 由于您正在编写异步代码,因此您可以利用并行处理子集合的优势!为此,每个操作都应创建自己的上下文。 This explains why it's faster.以下是使用建议的示例:
private async Task UpdateAddresses(List<Address> addressesToUpdate)
using(var context = new Context())
var existingAddressIds = await context.Addresses
.Where(a => addressesToUpdate.Contains(a.AddressId))
.ToListAsync()
.ConfigureAwait(false);
existingAddressIds.ForEach(a => context.Addresses.Remove(a));
await context.SaveChangesAsync().ConfigureAwait(false);
【讨论】:
以上是关于EF7 如何处理嵌套实体的更新操作的主要内容,如果未能解决你的问题,请参考以下文章