2015-12-01 11 views
6

Próbuję znaleźć najlepsze praktyki podczas aktualizowania obiektu i wszystkich jego dzieci. Na przykład; Mam usługę aktualizacji "Pracodawca", która aktualizowałaby podmiot pracodawcy i "Adres" podmiotów pracodawcy oraz podmioty "Telefoniczne" każdego "Adresu". Użytkownik może dodawać nowe adresy do obecnego pracodawcy lub może aktualizować aktualne adresy lub może usunąć niektóre, to samo dotyczy telefonów z każdego adresu. Czy możesz mi pomóc napisać idealny kod, który poradzi sobie z tym scenariuszem?EF7 Jak obsłużyć operację aktualizacji zagnieżdżonych encji

Używam EF7 rc1 i używam Automappera do odwzorowania Dto na Entity w mojej usłudze.

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

Moja metoda serwisowa;

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

Odpowiedz

0

Ten przykład wygląda na przyzwoity sposób obsługi kolekcji dzieci. Każda kolekcja musi zostać ręcznie sprawdzona pod kątem wykonanej akcji. (Przy użyciu rodzajowych brzmi dobrze, ale zawsze gryzie się w jakiś sposób Zwykle wydajność.).

Mając to na uwadze, oto kilka zaleceń:

  • Move kolekcja dziecko obsługi w odrębnych metod/usług.
  • Jeśli w przypadku zapytania dotyczącego istniejących obiektów pobierzesz całą kolekcję w jednym zapytaniu, wówczas powtórz wyniki w pamięci.
  • Odkąd piszesz kod asynchroniczny, możesz równolegle przetwarzać zbiory podrzędne! Aby to zrobić, każda operacja powinna stworzyć własny kontekst. This explains why it's faster.

Oto przykład stosując zalecenia:

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);  
    } 
} 
Powiązane problemy