Suppose a customer has many phone numbers and a phone number has only one customer.
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);
}
}
If I do an EF mapping like this and run it, every time I set phone numbers it will create new PhoneNumbers but not delete the old ones. There are no other entities referencing phone numbers, I don't even expose it on my dbcontext, is there a way to tell EF that Customer
owns PhoneNumbers
completely and therefore if phone numbers were removed from the collection they should be deleted?
I realize that there's a dozen ways to hack around this problem, but this isn't a weird edge case, what's the "right" way to handle this.
EntityState.Added : EntityState.Modified; context.SaveChanges(); } } Note that when you change the state to Modified all the properties of the entity will be marked as modified and all the property values will be sent to the database when SaveChanges is called.
This can be achieved in several ways: setting the EntityState for the entity explicitly; using the DbContext. Update method (which is new in EF Core); using the DbContext. Attach method and then "walking the object graph" to set the state of individual properties within the graph explicitly.
I had the exact same question :)
This answer on identifying relationships solved my issue.
Note: You have to load the collection (eagerly, explicitly or lazily) so that it can be tracked before setting the new values and calling save. Otherwise you will not be replacing the collection but, just be adding to it.
For example:
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();
This will remove the previous collection values from the 'collection table' and only add the newly set values.
Hope that helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With