gpt4 book ai didi

c# - Entity Framework + LINQ + "Contains"== 超慢?

转载 作者:可可西里 更新时间:2023-11-01 03:06:54 26 4
gpt4 key购买 nike

在尝试重构一些最近变得非常慢的代码时,我遇到了一个代码块,它的执行时间超过 5 秒。

代码由 2 条语句组成:

IEnumerable<int> StudentIds = _entities.Filters
.Where(x => x.TeacherId == Profile.TeacherId.Value && x.StudentId != null)
.Select(x => x.StudentId)
.Distinct<int>();

_entities.StudentClassrooms
.Include("ClassroomTerm.Classroom.School.District")
.Include("ClassroomTerm.Teacher.Profile")
.Include("Student")
.Where(x => StudentIds.Contains(x.StudentId)
&& x.ClassroomTerm.IsActive
&& x.ClassroomTerm.Classroom.IsActive
&& x.ClassroomTerm.Classroom.School.IsActive
&& x.ClassroomTerm.Classroom.School.District.IsActive).AsQueryable<StudentClassroom>();

所以它有点困惑,但首先我从一个表(过滤器)中获得一个不同的 Id 列表,然后我使用它查询另一个表。

这些是相对较小的表,但仍然需要 5 秒以上的查询时间。

我把它放在 LINQPad 中,它显示它首先执行底部查询,然后运行 ​​1000 个“不同”查询。

一时兴起,我通过在末尾添加 .ToArray() 来更改“StudentIds”代码。这将速度提高了 1000 倍……现在完成相同的查询大约需要 100 毫秒。

这是怎么回事?我做错了什么?

最佳答案

这是 Linq 中延迟执行的陷阱之一:在您的第一种方法中,StudentIds 实际上是一个 IQueryable,而不是内存中的集合。这意味着在第二个查询中使用它会在数据库上再次运行查询 - 每一次。

通过使用 ToArray() 强制执行第一个查询使 StudentIds 成为内存中的集合,并且 Contains 成为第二个查询中的一部分将遍历包含固定项目序列的集合 - 这将映射到等效于 SQL where StudentId in (1,2,3,4) 查询的内容。

这个查询当然会快得多,因为您预先确定了这个序列,而不是每次执行 Where 子句时。您不使用 ToArray() (我认为)的第二个查询将映射到带有 where exists (...) 子查询的 SQL 查询,该子查询针对每行。

关于c# - Entity Framework + LINQ + "Contains"== 超慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10080732/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com