表达式在 LINQ 中执行时是否枚举参数
本文关键字:是否 枚举 参数 执行 LINQ 表达式 | 更新日期: 2023-09-27 18:32:53
我有一个使用 LINQ 返回IQueryable
的方法
return eventFacade.GetNewBuildingEvents()
.Where(EventPredicates.IsBuildingOwner(
memberFacade.GetFriendsAndColleagues(m).Select(y => y.Id))
)
GetFriendsAndColleagues(m).Select(y => y.Id)
返回一个 IEnumerable
public static Expression<Func<Event, bool>> IsBuildingOwner(IEnumerable<int> friendids)
{
return
x =>
x.Building.BuildingMembers.Where(k => k.Type == MemberType.Owner)
.Any(p => friendids.Contains(p.Member.Id));
}
总的来说,我仍在学习 LINQ 和 C#。我知道IQueryable
和IEnumerable
延迟执行,我知道使用IQueryable
进行过滤发生在 databsae 中,而IEnumerable
发生在内存中。
我还知道,在迭代集合的情况下,最好枚举集合,以便每次迭代都不会调用数据库。
因此,当我执行最后一个查询时,传递给表达式的IEnumerable
是否会被枚举一次,然后用于比较 GetNewBuildingEvents()
返回的每个项目
或
它是否在每次比较时调用数据库以获取列表?
如果你想知道迭代了多少次,只需在迭代时执行一些可观察副作用的序列上运行该代码,以便你可以看到它发生了多少次。
可以使用以下帮助程序方法将任何序列包装成一个序列,该序列将在每次迭代时写出到控制台。
public static IEnumerable<T> NoisyWrapper<T>(IEnumerable<T> source)
{
Console.WriteLine("Rabble rabble rabble!!!");
foreach (var item in source)
yield return item;
}
这样就解决了一般情况下的问题。
在特定情况下,序列只应迭代一次。 您正在创建一个表达式,该表达式已编译为数据库查询并在数据库端执行。 在适当的上下文(您的上下文)中使用大多数基于 SQL 的查询提供程序的IEnumerable
Contains
将转换为 SQL 中的IN
子句。 IEnumerable
需要迭代一次才能提供 IN
子句的值,并且不需要多次迭代。