EF Core 3.0 .Include 无法按预期工作且速度超慢

Her*_*man 5 c# ef-core-2.2 ef-core-3.0

我在 EF Core 2.0 中有这样的 linq 查询,它可以正常工作,但是当我升级到 EF Core 3.0 时它总是超时。我在query = query.Where(x => x.Questions);.
我的问题是我想返回带有过滤问题的课程,例如仅 Take(10) 或仅显示特定范围而非所有问题的 .Where 条件。

var query = _courseRepository.Table;
query = query.Where(x => x.Id == id);
query = query.Include(x => x.Questions);
query = query.Include(x => x.CourseYear);
query = query.Include(x => x.CourseSubject);
query = query.Include(x => x.Instructors).ThenInclude(y => y.User);
query = query.Include(x => x.Instructors).ThenInclude(y => y.Course);
query = query.Include(x => x.Instructors).ThenInclude(y => y.CourseClass);
query = query.Include(x => x.CourseSections);
query = query.Include(x => x.CourseSections).ThenInclude(y => y.Lessons);
query = query.Include(x => x.CourseClasses);
query = query.Include(x => x.UserCourses).ThenInclude(y => y.User);
var result = query.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

ttu*_*tes 8

EFCore 3.0 更改了使用生成的查询.Include(),您正在遇到笛卡尔爆炸问题;

具体来说,现在文档中有以下红色警告:

警告

从 3.0.0 版本开始,每个 Include 都会导致将额外的 JOIN 添加到关系提供程序生成的 SQL 查询中,而以前的版本会生成额外的 SQL 查询。这会显着改变查询的性能,无论好坏。特别是,具有大量 Include 运算符的 LINQ 查询可能需要分解为多个单独的 LINQ 查询,以避免笛卡尔爆炸问题。

解决方案是现在根据文档执行多个查询。

它的超级不幸加载实体图,常见于高度规范化的数据,性能不佳,但这是它当前的 EF 状态。

请参阅:加载相关数据并滚动直到看到红色。

  • @OffirPe'er 这里也一样。这实在是不幸。我不明白为什么 EF 团队至少不给我们一个改变这种行为的选项。 (2认同)

小智 0

var query = _courseRepository.Table
.Include(x => x.Questions)
.Include(x => x.CourseClasses)
.Include(x => x.CourseYear)
.Include(x => x.CourseSubject);

var course = await query.FirstOrDefaultAsync(x => x.Id == id);

query.Include(x => x.Instructors).ThenInclude(y => y.User).SelectMany(a => a.Instructors).Load();
query.Include(x => x.Instructors).ThenInclude(y => y.Course).SelectMany(a => a.Instructors).Load();
query.Include(x => x.Instructors).ThenInclude(y => y.CourseClass).SelectMany(a => a.Instructors).Load();

query.Include(x => x.CourseSections).ThenInclude(y => y.Lessons).SelectMany(a => a.CourseSections).Load();

query.Include(x => x.UserCourses).ThenInclude(y => y.User).SelectMany(a => a.UserCourses).Load();
Run Code Online (Sandbox Code Playgroud)