使用Entity Framework加载嵌套关系

时间:2018-01-09 14:09:46

标签: c# linq entity-framework-6

我正在寻找一种方法来使用where子句加载嵌套关系。

想象一下下面的查询示例。

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'

通过这样做很容易加载来自这些实体的所有信息:

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

但是如何在上面发布的查询中模拟我的where子句?

知道我使用的是Entity Framework 6,是否可以这样做?我已经研究过这个并没有找到我的问题的答案。

编辑1

我问这个,因为我试图在WCF Restful aplication中使用它。并且它以StackOverflowException返回,可能是因为我为实体构建了向后引用时的循环引用。

3 个答案:

答案 0 :(得分:2)

从查看LINQ查询,这样的事情应该有效:

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

答案 1 :(得分:2)

基本上,你应该考虑在另一个方向重新思考你的EF-Query(假设你有1:很多关系):

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

然后,您有一份名为John的员工名单及其相关经理和董事。

从导演开始的问题是,您可以无条件地加载所有相关的管理器,或者您需要将结果选择到新的数据结构中,而不是使用默认的EF映射。

答案 2 :(得分:1)

作为使用导航属性的替代方法,您可以简单地在linq等效项中翻译您的SQL查询。 导航属性很棒但确保您确实需要它们。

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,
            };

此外,将您的查询投射到某种专用DTO上肯定会解决您的循环引用

修改 尽量不要直接序列化您的域,而是创建外部图层所需形状的视图模型。 如果您确实需要将实体暴露给外部世界,则可能需要关闭延迟加载。 事实上,关闭延迟加载仍然是Lazy loading and serialization don’t mix well