How do I detach objects in Entity Framework Code First?
Asked Answered
G

3

199

There is no Detach(object entity) on the DbContext.

Do I have the ability to detach objects on EF code first?

Gaynellegayner answered 8/4, 2011 at 18:15 Comment(0)
K
190

If you want to detach existing object follow @Slauma's advice. If you want to load objects without tracking changes use:

var data = context.MyEntities.AsNoTracking().Where(...).ToList();

As mentioned in comment this will not completely detach entities. They are still attached and lazy loading works but entities are not tracked. This should be used for example if you want to load entity only to read data and you don't plan to modify them.

Kelsey answered 8/4, 2011 at 20:0 Comment(10)
@Ladislav: This is indeed probably what Lol coder meant. I've never used and thought about this method although I often load object lists and dispose the context at once, something like using(ctx){ return ctx....ToList(); }. In such cases using AsNoTracking() would make much sense because I'd save filling up the object context unnecessarily. I guess it would probably have a performance and memory consumption benefit especially for large lists, right?Liberty
@Slauma: Yes it has performance benefit. That is actually why this method exists. Using this approach in ObjectContext API is little bit more complicated.Kelsey
Does this disable lazy loading?Gaynellegayner
Actually this will not disable lazy loading it will only disable change tracking and improve performance = entity is still attached. I found it after answering this question so you should mark @Slauma's one as a valid answer.Kelsey
This is what I want. I want lazy loading and the ability to only modify a detached entity.Gaynellegayner
@Ladislav: To your comment above from Apr 16: Did you test this with a model with lazy loading enabled? I have just used AsNoTracking in a model without lazy loading and the entities are not attached to the context. Perhaps it is so: 1) Change tracking is always disabled (no snapshot is taken). 2) If lazy loading is disabled the entity is loaded in detached state, otherwise the entity is attached (necessary for lazy loading).Liberty
what is the solution? AsNoTracking() or Include() or dbContext.Entry(entity).State = EntityState.Detached;Erose
AsNoTrcking() is not work for me. I used "entity.Configuration.ProxyCreationEnabled = false".Sklar
Entities loaded via AsNoTracking() are yielded in Detached state.Demmy
This is not detaching objects, this is NOT attaching them.Picrotoxin
L
332

This is an option:

dbContext.Entry(entity).State = EntityState.Detached;
Liberty answered 8/4, 2011 at 19:0 Comment(8)
Can I do this when retrieving objects that returns an IQueryable?Gaynellegayner
@Lol coder: I am not sure if I understand you right, but entity must be a materialized object of a type which is part of your model classes (Person, Customer, Order, etc.). You cannot directly pass in an IQueryable<T> into dbContext.Entry(...). Is that the question you meant?Liberty
what is the solution? AsNoTracking() or Include() or dbContext.Entry(entity).State = EntityState.Detached;Erose
@EladBenda: It depends. If you want to detach an object that is already attached to the context, set the state to Detached. If you want to load entities from the DB without attaching them at all to the context (no change tracking), use AsNoTracking.Liberty
I found an interesting problem with this method. Even though the entity may be a proxy class, lazy loading will not work after you change its state to Detached.Haberdasher
@Haberdasher : this is the expected behavior, since the entity has no link with the context.Gamb
@rcdmk If you get an entity with AsNoTracking like in the other answer then lazy loading will still work. This method will not.Haberdasher
don't forgot SaveChange and EntityState.Modified before EntityState.DetachedMicroscope
K
190

If you want to detach existing object follow @Slauma's advice. If you want to load objects without tracking changes use:

var data = context.MyEntities.AsNoTracking().Where(...).ToList();

As mentioned in comment this will not completely detach entities. They are still attached and lazy loading works but entities are not tracked. This should be used for example if you want to load entity only to read data and you don't plan to modify them.

Kelsey answered 8/4, 2011 at 20:0 Comment(10)
@Ladislav: This is indeed probably what Lol coder meant. I've never used and thought about this method although I often load object lists and dispose the context at once, something like using(ctx){ return ctx....ToList(); }. In such cases using AsNoTracking() would make much sense because I'd save filling up the object context unnecessarily. I guess it would probably have a performance and memory consumption benefit especially for large lists, right?Liberty
@Slauma: Yes it has performance benefit. That is actually why this method exists. Using this approach in ObjectContext API is little bit more complicated.Kelsey
Does this disable lazy loading?Gaynellegayner
Actually this will not disable lazy loading it will only disable change tracking and improve performance = entity is still attached. I found it after answering this question so you should mark @Slauma's one as a valid answer.Kelsey
This is what I want. I want lazy loading and the ability to only modify a detached entity.Gaynellegayner
@Ladislav: To your comment above from Apr 16: Did you test this with a model with lazy loading enabled? I have just used AsNoTracking in a model without lazy loading and the entities are not attached to the context. Perhaps it is so: 1) Change tracking is always disabled (no snapshot is taken). 2) If lazy loading is disabled the entity is loaded in detached state, otherwise the entity is attached (necessary for lazy loading).Liberty
what is the solution? AsNoTracking() or Include() or dbContext.Entry(entity).State = EntityState.Detached;Erose
AsNoTrcking() is not work for me. I used "entity.Configuration.ProxyCreationEnabled = false".Sklar
Entities loaded via AsNoTracking() are yielded in Detached state.Demmy
This is not detaching objects, this is NOT attaching them.Picrotoxin
G
15

Both previous answers provide good instructions, however, both might leave you with the entities still loaded into EF's context and/or its Change Tracker.

This is not a problem when you are changing small data sets, but it will become an issue when changing large ones. EF would have increased memory and resource usage, which in turn would reduce the procedure performance as it uses more data/entities.

Both other approaches are valid but, In this case, Microsoft recommends cleaning the Change tracker instead of detaching the entities individually

Clearing the Change tracker on the data changing loop (which changes a chunk of data for instance) can save you from this trouble.

context.ChangeTracker.Clear();

This would unload/detach all entities and its related changeTracker references from the context, so use with care after your context.SaveChanges().

Giacomo answered 14/12, 2021 at 2:8 Comment(8)
both would leave you with the entity still loaded into EF's Change Tracker -- That's not true. Detaching an object removes it from the change tracker. If the entity is a lazy-loading proxy then it has a reference to the context, but that's not the same as being attached to it (Ladislav's phrasing is a bit ambiguous here).Colloquialism
Hi Gert, You can verify it with a quick test. The entity remains in the ChangeTracker with a state of detached. Similar to a memory leak (but unfortunately by design..). Calling the Clear command removes all of the instantiated entity objects from the ContextGiacomo
Of course the state is detached, what else? Even if you create a brand new entity that has never even seen a context its state is detached. It's just EF's way of saying: don't know this one, nothing to do with it. The alternative would be to throw an exception when verifying the state of any entity outside the context. Of course nobody wants that.Colloquialism
and yet EF retains it in memory detached like a memory leakGiacomo
Then please show how. Your statement doesn't have any backing.Colloquialism
Only lazy-loading proxies. And the context doesn't have reference to them when they're detached. It's not that EF keeps them in memory. It's the application that may keep proxies alive for a long time, which may cause a memory leak because the context they refer to can't be GC-ed. That's not EF's fault. Your statements are clearly rooted in the misconception that when EF reports an object as detached, it has to have it in its change tracker somehow. It hasn't.Colloquialism
You are getting there, still have a little to learn from the usage of EF though. Good luck on your effortsGiacomo
Thanks @TheFabio - this solved a massive performance issue when bulk inserting very large graphs in EF. To solve it, I used your line after saving each entity, and the performance increase and memory usage improvement was awesome. Thanks!Bring

© 2022 - 2024 — McMap. All rights reserved.