2015-12-01 3 views
6

Ich versuche, die Best Practices beim Aktualisieren einer Entität und alle ihre untergeordneten Elemente zu ermitteln. Beispielsweise; Ich habe einen "Arbeitgeber" -Update-Dienst, der die Arbeitgeber-Entität und die "Adress" -Entitäten des Arbeitgebers und die "Telefon" -Entitäten jeder "Adresse" aktualisiert. Der Benutzer kann dem bestehenden Arbeitgeber neue Adressen hinzufügen, oder er kann die aktuellen Adressen aktualisieren, oder er kann einige löschen, gleiches gilt für die Telefone jeder Adresse. Könnten Sie mir helfen, den idealen Code zu schreiben, der dieses Szenario behandelt?EF7 Wie die Update-Operation für verschachtelte Entitäten behandelt

Ich benutze EF7 rc1 und ich benutze Automapper, um die Dto zu Entity in meinem Dienst zuordnen.

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; } 
} 

Meine Servicemethode;

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

Antwort

0

Dieses Beispiel sieht wie eine anständige Möglichkeit aus, mit untergeordneten Auflistungen umzugehen. Jede Sammlung muss manuell auf die ausgeführte Aktion überprüft werden. (Die Verwendung von Generika klingt gut, aber immer beißt zurück in irgendeiner Weise Typischerweise Leistung..)

In diesem Sinne, hier ein paar Empfehlungen:

  • verschieben das Kind Sammlung in separate Methoden der Handhabung/Dienstleistungen.
  • Wenn Sie nach vorhandenen Entitäten suchen, rufen Sie die gesamte Auflistung in einer Abfrage ab und führen Sie die Ergebnisse anschließend im Speicher durch.
  • Da Sie Async-Code schreiben, können Sie die parallelen Verarbeitung der untergeordneten Sammlungen nutzen! Um dies zu tun, sollte jede Operation ihren eigenen Kontext erstellen. This explains why it's faster.

Hier ist ein Beispiel, die Empfehlungen mit:

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);  
    } 
} 
Verwandte Themen