简体   繁体   中英

Loading nested relationships using Entity Framework

I'm looking for a way to Load nested relationships with a where clause.

Imagine that query example below.

select * 
from directors d
inner join managers m 
  on d.id = m.director
inner join employees e
  on m.id = e.manager
where e.name = 'John'

It's easy to load all the information from those entities by doing this:

ctx.Directors.Include(x => x.Managers.Select(y => y.Employees)).ToList();

but how can I simulate my where clause at the query posted above?

Knowing that I'm using Entity Framework 6, is it possible to do that? I have researched for this and didn't find an answer to my question.

EDIT 1

I'm asking this, because I'm trying to use this in a WCF Restful aplication. And it's returning with a StackOverflowException, probably because of a circular reference when I build the backward reference for the entities.

From looking at your LINQ query, something like this should work:

from director in ctx.Directors
from manager in director.Managers
from employee in manager.Employees
where employee.Name == "John"
select director;

Basically, you should consider re-thinking your EF-Query in the other direction (Assuming that you have 1:many relationships):

ctx.Employees
    .Include(x => x.Manager.Director)
    .Where(x => x.Name == "John")
    .ToList();

Then you have a list of employees named John with their associated managers and directors.

The problem with starting at directors is, you can either load all related managers unconditionally, or you need to select your results into a new data structure instead of using the default EF mapping.

As an alternative to using navigational properties you could simply translate your sql query in the linq equivalent. Navigational properties are great but make sure you actually need them.

var query = from director in ctx.Directors
            join manager in ctx.Managers
                on director.Id equals manager.DirectorId
            join employee in ctx.Employees
                on manager.Id equals employee.ManagerId
            where employee.Name == "John"
            select new
            {
                director,
                manager,
                employee,
            };

moreover projecting your queries to some sort of dedicated DTOs will certainly solve your circular references as well

Edit Try not to serialize your domain directly, but rather create the view model in the shape needed for outside layers. If you really need to expose your entities to the outside world, you might want to turn off lazy loading. As a matter of fact turn off lazy loading anyways as Lazy loading and serialization don't mix well

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM