EF Lambda:包含路径表达式必须引用导航属性[重复]

Posted

技术标签:

【中文标题】EF Lambda:包含路径表达式必须引用导航属性[重复]【英文标题】:EF Lambda: The Include path expression must refer to a navigation property [duplicate] 【发布时间】:2013-04-05 12:43:19 【问题描述】:

这是我的表达:

Course course = db.Courses
  .Include(
    i => i.Modules.Where(m => m.IsDeleted == false)
      .Select(s => s.Chapters.Where(c => c.IsDeleted == false))
  ).Include(i => i.Lab).Single(x => x.Id == id);

我知道原因是模块部分中的Where(m => m.IsDeleted == false),但为什么会导致错误?更重要的是,我该如何解决?

如果我删除 where 子句,它可以正常工作,但我想过滤掉已删除的模块。

【问题讨论】:

【参考方案1】:

.Include 用于从数据库中急切地加载相关实体。 IE。在您的情况下,请确保课程中加载了模块和实验室的数据。

.Include 中的 Lamba 表达式应该告诉实体框架要包含哪个相关表。

在您的情况下,您还尝试在包含内执行条件,这就是您收到错误的原因。

看起来您的查询是这样的:

查找与给定 ID 匹配的课程,以及相关模块和实验室。只要匹配的模块和章节没有被删除。

如果这是正确的,那么这应该有效:

Course course = db.Courses.Include(c => c.Modules)
                          .Include(c => c.Lab)
                          .Single(c => c.Id == id && 
                                       !c.Module.IsDeleted &&
                                       !c.Chapter.IsDeleted);

【讨论】:

这确实是错误的。您将从模块和实验室表中获取所有项目。【参考方案2】:

但是为什么会导致错误呢?

我可以想象,有时 EF 团队会后悔他们引入这种 Include 语法的那一天。 lambda 表达式表明,任何有效的 linq 表达式都可以用来巧妙地操纵预加载。但太糟糕了,并非如此。正如我在here 解释的那样,lambda 仅用作底层“真实”Include 方法的伪装字符串参数。

我该如何解决?

最好是投影到另一个类(例如,DTO)

db.Courses.Select(x => new CourseDto 
    Id = x.Id,
    Lab = x.Lab,
    Modules = x.Modules.Where(m => !m.IsDeleted).Select( m => new ModuleDto 
        Moudle = m,
        Chapters = x.Chapters.Where(c => c.IsDeleted)
    
).Single(x => x.Id == id);

但这对你来说可能是一个重大的修改。

另一个选项是禁用延迟加载并通过Load command 预加载上下文中未删除的课程模块和章节。关系修复将填充正确的导航属性。 LabInclude 将正常工作。

顺便说一句,这个功能有一个change request。

【讨论】:

以上是关于EF Lambda:包含路径表达式必须引用导航属性[重复]的主要内容,如果未能解决你的问题,请参考以下文章

包含路径表达式必须引用 type.in 预加载中定义的导航属性

包含路径表达式必须引用在类型上定义的导航属性(使用 LINQ 选择数据)

Include 中使用的 Lambda 表达式无效。 EF6,导航属性

EF 6 代码首先,在导航属性上使用包含更改外键 ID 会导致“发生引用完整性约束违规”错误

如何在EF6.1中过滤掉子集合

EF:“包含”导航属性,当使用“选择”投影创建包装对象时