DbCollectionEntry should have Add, Remove, Attach methods


For a particular user case, I want to manipulate a collection but prevent it from lazy loading. For Remove to have any effect, I have to do something like this:
db.Configuration.LazyLoadingEnabled = false;
db.Configuration.LazyLoadingEnabled = true;
or even worse, if we cannot assume room is a change tracking proxy, then we have to do:
    .GetRelatedCollection<Users>(relationshipName, targetRoleName)
just to obtain the IRelatedEnd.

If DbCollectionEntry had Attach I could do someting like this:
db.Entry(room).Collection(r => r.Users).Attach(user);
db.Entry(room).Collection(r => r.Users).Remove(user);


ajcvickers wrote Mar 29, 2013 at 2:18 AM

I started looking at this and made some progress but several things came up that make this more complicated than it at first seems. It does seem that it would be useful to have an API that can be used to manipulate a related collection without:
  • Triggering lazy loading
  • Requiring the use of DetectChanges
However, it's not clear to me exactly what the semantics of Add/Attach/Remove are in such a case. For example, is it purely about manipulating the relationships between entities, or is it also a means to start tracking entities? If I call Add on an untracked entity it seems clear that it should both become tracked in the Added start and added to the collection. There are many other similar simple cases. But then consider what happens when I call Attach for an entity that is in the Added state. Should it make the entity Unchanged/Modified before adding it to the collection? If so, should calling Add on an Unchanged entity make it Added?

Another interesting case is calling Attach on an entity that is Unchanged but for which adding it to the collection would require the FK to be modified. Should it modify the FK and put the entity in the Modified state, should it modify the FK silently such the entity is still Unchanged but has actually been changed, or should it throw like DbSet.Attach does?

Also, consider Remove. In the example above, Attach is being called before Remove. This makes sense. What if Remove is called for an untracked entity? Should it throw? Should it Attach the entity automatically and then Remove it? What about if Remove is being called for a Modified entity but where the principal is in the Added state? Should this detach the entity, or should it stay Modified? What about if it was Unchanged instead of Modified?

I believe that we need to do something here, but I think we probably need to have a better understanding of what the API is really for and then try to come up with a set of a consistent and relatively easy to understand behaviors for each combination of entity state and operation.

RoMiller wrote Apr 4, 2013 at 5:49 PM

EF Team Triage: Given the complexities mentioned by Arthur and considering where we are in the EF6 release we are moving this to Future to be reconsidered for a future release.

ajcvickers wrote Aug 2, 2013 at 5:23 PM

Note: whatever we do here should not only not cause lazy loading but should also result in the change being recognized immediately without a call to DetectChanges being needed.