Supponiamo che un cliente abbia molti numeri di telefono e che un numero di telefono abbia un solo cliente.
public class PhoneNumber : IValueObject {
public string Number {get; set;}
public string Type {get; set;}
}
public class Customer : IEntity {
public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support
public void SetPhones(params PhoneNumber[] phones) {
this.phones.Clear();
this.phones.AddRange(phones);
}
}
Se faccio una mappatura EF come questa e la eseguo, ogni volta che imposto i numeri di telefono creerà nuovi PhoneNumbers ma non cancellerà quelli vecchi. Non ci sono altre entità che fanno riferimento ai numeri di telefono, non lo espongo nemmeno sul mio dbcontext, c'è un modo per dire a EF che il Customer
possiede PhoneNumbers
completamente e quindi se i numeri di telefono sono stati rimossi dalla collezione dovrebbero essere cancellati?
Mi rendo conto che esiste una dozzina di modi per aggirare questo problema, ma questo non è un caso strano, qual è il modo "giusto" per gestirlo.
Ho avuto la stessa identica domanda :)
Questa risposta sull'identificazione delle relazioni ha risolto il mio problema.
Nota: devi caricare la raccolta (con entusiasmo, in modo esplicito o pigramente) in modo che possa essere monitorata prima di impostare i nuovi valori e il salvataggio delle chiamate. Altrimenti non rimpiazzerai la collezione, ma aggiungendoti ad essa.
Per esempio:
var entity = unitOfWork.EntityRepository.GetById(model.Id);
// I have something like this to load collection because
// I don't have the collection's entities exposed to the context
unitOfWork.EntityRepository.LoadCollection(entity, e => e.CollectionProperty);
entity.CollectionProperty = newCollectionValuesList;
unitOfWork.Save();
Questo rimuoverà i precedenti valori di raccolta dalla 'tabella di raccolta' e aggiungerà solo i nuovi valori impostati.
Spero possa aiutare.
Primo (facoltativo):
Ti consiglio di fare
public ICollection<PhoneNumber> phones {get; private set;}
una proprietà virtual
, per consentire a Entity Framework di sapere che dovrebbe essere caricato in modo pigro (anche se non si dispone di Lazy Load abilitato, è una buona pratica).
public virtual ICollection<PhoneNumber> phones {get; private set;}
Secondo :
Aggiungi una proprietà di navigazione inversa sulla tua classe PhoneNumber
(sarà necessaria per ottenere la soluzione che ti do sotto):
public class PhoneNumber : IValueObject {
public string Number {get; set;}
public string Type {get; set;}
public virtual Customer {get; set;}
}
public class Customer : IEntity {
public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support
public void SetPhones(params PhoneNumber[] phones) {
this.phones.Clear();
this.phones.AddRange(phones);
}
}
Terzo (possibile soluzione per il tuo problema):
Rimuovi gli oggetti PhoneNumber
da Context invece di farlo dal Customer
:
public ICollection<PhoneNumber> phones {get; private set;} //ew at no encapsulated collection support
public void SetPhones(params PhoneNumber[] phones) {
Context.PhoneNumbers.RemoveRange(this.phones);
this.phones.AddRange(phones);
}
}