How to update an entity with collection property that has either new, updated or deleted entities?
See original GitHub issueI have the following models:
public class SubscriptionLine
{
public Guid Id { get; set; }
}
public class Subscription
{
public Guid Id { get; set; }
public IEnumerable<SubscriptionLine> SubscriptionLines { get; set; }
}
I’m syncing these models to a database from an external source where a subscription comes in with a bunch of subscription lines. All the Ids are generated by the external source. Therefore:
- I know whether the subscription is in the database or not. If it is not, I add it to the database using dbContext.Add, which will also add all the subscription lines. That’s just fine.
- If the subscription is already known to the database (i.e. it has been changed in the external source), I will have to update it, including the subscription lines. Every subscription line either
- Is new, in which it has to be inserted
- Is changed, in which case it has to be updated
- Is no longer part of the SubscriptionLines IEnumerable, in which case it has to be removed from the database.
I’m not sure how to accomplish this, as I read in the documentation that a call to Update sets the state of the Subscription entity and all the SubscriptionLines to Modified. However, this means that entities are being updated that are not yet part of the database, which will fail of course.
When the subscription entity is known to the database, I can of course remove it, which will remove all the subscription lines, and then reinsert it. However, this looks like an overkill strategy. I read that updating a collection i.e. clearing it and than adding the new items does not work.
I’m asking this here because I think this is a use case that makes sense to be documented in the official documentation.
Issue Analytics
- State:
- Created 2 years ago
- Comments:11 (6 by maintainers)
Thanks for pointing me at these docs, I must have missed them.
Code is now as follows:
LoadAsync turned out to be very helpful to filter out the entities to delete. There’s one major disadvantage to the current code, namely that I need to call
subEntry.GetDatabaseValuesAsync
to find out whether the entity has to be added or modified, even though I should already have this info in memory somehow by calling LoadAsync on the collection. @ajcvickers May be you have a suggestion to work around that?@leonardder There is no easy answer to this. EF needs to know whether each entity is new or not, but if the entities come to EF with pre-generated keys, then there is no way for EF to automatically distinguish new entities from existing ones. Further, there is no way for EF to know if an entity has been removed from a collection as opposed to never being there in the first place. This is discussed in Explicitly Tracking Entities in the documentation.
In general, the ways to deal with this are:
Also, consider voting to Turn-key Disconnected Entities Solution.