Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does Setting EntityState to Detached Empty a Property of type List<T>?

Using Entity Framework Code First, I have something like:

public class Foo
{
    public int Id { get; set; }

    public List<Bar> Bars { get; set; }
}    

Foo foo = (from f in ctx.Foos.Include("Bars") where f.Id == 42 select f).Single();

// At this point foo.Bars is populated

ctx.Entry(foo).State = EntityState.Detached;

// At this point foo.Bars is an empty List

Why does detaching an object cause it's property public List<string> Bars, which was explicitly and successfully included, to be emptied?

What is the correct procedure to detach an object that may have many properties?

like image 293
Eric J. Avatar asked Apr 26 '12 22:04

Eric J.


People also ask

What is EntityState detached?

An entity is in this state immediately after it has been created and before it is added to the object context. An entity is also in this state after it has been removed from the context by calling the Detach(Object) method or if it is loaded by using a NoTrackingMergeOption.

What does EntityState Modified do?

Updates are not sent to the database for entities in the Unchanged state. Added entities are inserted into the database and then become Unchanged when SaveChanges returns. Modified entities are updated in the database and then become Unchanged when SaveChanges returns.

What is detach in Entity Framework?

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).

What is EntityState in Entity Framework?

EF API maintains the state of each entity during its lifetime. Each entity has a state based on the operation performed on it via the context class. The entity state represented by an enum System.


1 Answers

The reason why the list is emptied is a combination of two rules in Entity Framework:

  1. When you detach an object only this object itself is detached without the objects any navigation properties refer to.

  2. The ObjectContext/DbContext does not allow to hold an object graph which is partially attached to the context and partially detached. Although this can happen as a temporary state when using POCOs EF will always fix this temporary state by automatically attaching detached objects in the graph inside of various methods (like Add, Attach, setting the state of an entity, etc.) or latest when SaveChanges is called.

This means that when you detach the root object from the context, EF will clear the list of children because: a) the children stay attached (rule 1) and b) a mix of detached and attached objects in the graph is not allowed (rule 2).

As far as I can tell there is no way to detach an object graph from the context while maintaining the original tree structure. You can detach the parent and then the children one after each other. As a result you have detached all objects of the tree from the context but the tree is destroyed at the same time - each navigation property is nullified.

The main purpose of detaching entities manually is to release them for garbage collection in situations where you have memory resource limitations and don't want and need to hold a huge amount of objects in the context. For this purpose it doesn't matter that the graph structure is destroyed.

I don't know why you need to detach objects from the context. But keep in mind that there is also the option to load entities from the database without attaching them to the context in the first place, like using AsNoTracking().

Another answer about the problem with some references to MSDN documentation is here: https://stackoverflow.com/a/7693732/270591

like image 174
Slauma Avatar answered Oct 04 '22 22:10

Slauma