EF Lambda:Include路径表达式必须引用导航属性

Ani*_*ola 10 c# lambda entity-framework asp.net-mvc-3 entity-framework-5

这是我的表达:

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);
Run Code Online (Sandbox Code Playgroud)

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

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

Mar*_*nce 12

.Include用于从数据库急切加载相关实体.即在您的情况下,确保模块和实验的数据加载课程.

里面的lamba表达式.Include应该告诉Entity Framework要包含哪些相关表.

在您的情况下,您还尝试在include中执行条件,这就是您收到错误的原因.

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

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

如果这是正确的,那么这应该工作:

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

  • 这是非常错误的.您将从模块和实验室表中获取所有项目. (3认同)

Ger*_*old 5

但为什么会导致错误呢?

我可以想象有时 EF 团队会后悔引入此Include语法的那一天。lambda 表达式表明任何有效的 linq 表达式都可以用于巧妙地操纵急切加载。但可惜,事实并非如此。正如我在这里所解释的,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);
Run Code Online (Sandbox Code Playgroud)

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

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

顺便说一句,有一个对此功能的更改请求。