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

这是我的表达:

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

.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); 

但为什么会导致错误呢?

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

我如何解决它?

最好是投射到另一个class级(比如说,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命令禁用延迟加载并在上下文中预加载课程中未删除的模块和章节。 关系修正将填充正确的导航属性。 Include for Lab将正常运行。

顺便说一下,此function有更改请求 。