11

这是我的表达:

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 子句,它可以正常工作,但我想过滤掉已删除的模块。

4

2 回答 2

12

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

里面的lamba表达式.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);
于 2013-04-12T21:53:20.500 回答
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);

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

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

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

于 2013-04-12T22:11:48.343 回答