Why child entites binds to parent automatically in entity framework

c# entity-framework entity-framework-6


I don't know this is a good or bad thing and how to adapt this.

Parent-Child has very simple and obvious relation.No big deal. You can see the code below:

Parent Object:

public class Parent
    public int Id {get;set;}
    public List<Child> Childs {get;set;}

Child Object

public class Child
    public int Id {get;set;}
    public int ParentId {get;set;}
    public Parent Parent {get;set;}

Somewhere around the code(say index method of the controller)

var parent = parentRepository.FindAll(x=> x.Id == 10).ToList();
var childCollection = childRepository.FindAll(x=> x.ParentId == parent.Id).ToList();

When i run the code above i expect a parent object with Childs Property is null and childCollection that has null Parent property. But this is not happening. After second line of code executed, parent.Childs fills with the child objects and every Parent property in a child object is equal to parent which i don't want it(should i want it?).

Why entityframework behaves like that? And which cases should i be aware off? What happens if i change the childCollection without knowing this behavior?

4/7/2016 2:26:54 PM

Accepted Answer

Yes, that's the normal behavior of EF. At the moment when the childCollection is materialized calling ToList, when you check parent instance again, relationship fixup will run and check if Child entities whose FK have the same value as the PK of your current parent have been loaded earlier in the object context. If that is the case, the Parent.Childs property will immediately be set with those Child entities. This doesn't have nothing to do with lazy loading, in fact your model doesn't meet all the requirements that lazy loading need, like your navigation properties should be virtual.

This behavior cannot be disabled but if you use AsNoTracking extension method at the time to build your queries, the entities returned will not be cached in the DbContext:

var query= context.Childs.AsNoTracking().Where(c=>c.ParentId==10);

You can also find more details in this excellent post

5/23/2017 12:15:51 PM

Popular Answer

Like many modern ORMs, Entity Framework is designed not only to map your queries results to entities (objects), but to map their relationships to properties. If you declare a navigation property (such as you have done with Childs or Parent properties in your classes), EF will (lazily) map those properties to their referenced entities automatically (you can find more about navigation properties here).

This behavior is by design and has the intent to avoid explicitly do queries using joins, and makes it unnecessary to call childRepository.FindAll(x=> ... because all related Child entities are loaded by EF as soon as you access the Childs property in your Parent object.

Remember also that EF implements a change tracking system, so if you modify entities fetched from the database, EF will track those changes and persists them the first time you call SaveChanges on your context.

As a side note, EF architecture is really an example of the UnitOfWork and Repository patterns used together (DbContext is a UoW and each DbSet works like a Repository), so I strongly suggest you to read more about EF to avoid misusing its features or re-implementing them yourself using another abstraction (e.g. your Repositories).

Related Questions


Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow