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

时间:2013-04-12 20:54:22

标签: c# asp.net-mvc-3 entity-framework lambda 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);

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

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

2 个答案:

答案 0 :(得分:12)

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

.Include中的lamba表达式应该告诉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);

答案 1 :(得分:4)

  

但为什么会导致错误?

我可以想象,有时EF团队会在他们引入这种Include语法的那一天感到遗憾。 lambda表达式表明任何有效的linq表达式都可以用于巧妙地操纵急切加载。但太糟糕了,不是这样。正如我解释here,lambdas仅作为基础“真实”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的上下文中预加载课程中未删除的模块和章节。关系修正将填充正确的导航属性。 Include的{​​{1}}将正常工作。

顺便说一下,此功能有change request