【问题标题】:EF Core 3.0 .Include does not work as expected and Super SlowEF Core 3.0 .Include 无法按预期工作并且超级慢
【发布时间】:2019-11-03 03:08:36
【问题描述】:

我在 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();

【问题讨论】:

  • 请使用 SQL Trace 来获取 2.2 正在执行的 SQL。然后对 3.0 执行相同的操作。请在您的问题中分享它们。
  • I found the issue in query = query.Where(x => x.Questions);. 该代码不在您的问题中。
  • 我想知道如何返回包含条件的问题,因为我尝试了几种方法它总是返回所有列表。
  • 看起来您正在使用.Include 处理一对多或多对多关系。您不应该为此使用它 - 您应该只将 .Include() 用于零或一对一或多对一关系。
  • @Dai 来自 EF Docs 是允许这个。包括一对多,你的意思是你不应该使用它。

标签: c# ef-core-2.2 ef-core-3.0


【解决方案1】:

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

现在文档中有如下红色警告:

注意

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

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

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

请参阅:正在加载 Related Data 并滚动直到看到红色。

【讨论】:

  • Efcore3 拖慢了我的应用程序,我不得不将其恢复到 2.2 版
  • @OffirPe'er 这里也一样。这真的很不幸。我不明白为什么 EF 团队至少不给我们一个选项来改变这种行为。
  • @SebastianBrandesKraaijenzank 在 EF-Core 5 中,他们将拥有此选项,但我暂时不会冒险使用他们
【解决方案2】:
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();

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-26
    • 2018-05-03
    • 2020-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-30
    相关资源
    最近更新 更多