【问题标题】:EF7 How to handle the update operation for nested entitiesEF7 如何处理嵌套实体的更新操作
【发布时间】: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);
            }
        }
 }

【问题讨论】:

    标签: c# entity-framework asp.net-core entity-framework-core


    【解决方案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);    
       }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-05-07
      • 1970-01-01
      • 2021-07-28
      • 2017-12-16
      • 2022-06-27
      • 2019-06-01
      • 2012-03-30
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多