2015-12-01 6 views
6

エンティティを更新するときのベストプラクティスとそのすべての子を把握しようとしています。例えば;私は、雇用者のエンティティと「住所」エンティティと各「住所」の「電話」エンティティを更新する「雇用者」更新サービスを持っています。ユーザーは、既存の雇用主に新しいアドレスを追加することも、現在のアドレスを更新することも、削除することもできます。各アドレスの電話にも同じことが適用されます。このシナリオを処理する理想的なコードを書くのを助けてください。EF7ネストされたエンティティの更新操作を処理する方法

私は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); 
      } 
     } 
} 

答えて

0

この例は、子コレクションをうまく処理する方法のようです。各コレクションは、実行されたアクションについて手動でチェックする必要があります。 (ジェネリックを使用すると良い音が、常にバック何らかの方法で刺さ一般的に、パフォーマンスを。。)を念頭に置いて

、ここではいくつかの提案です:

  • 移動し、別の方法/サービスに取り扱う子コレクション。
  • 既存のエンティティをクエリする場合は、コレクション全体を1つのクエリで取得し、結果をメモリ内で反復処理します。
  • 非同期コードを作成しているので、子コレクションを並行して処理することができます。これを行うには、各操作で独自のコンテキストを作成する必要があります。

    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);  
        } 
    } 
    
    This explains why it's faster.

は、ここで推奨を使用した例です

関連する問題