表达式在 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#。我知道IQueryableIEnumerable延迟执行,我知道使用IQueryable进行过滤发生在 databsae 中,而IEnumerable发生在内存中。

我还知道,在迭代集合的情况下,最好枚举集合,以便每次迭代都不会调用数据库。

因此,当我执行最后一个查询时,传递给表达式的IEnumerable是否会被枚举一次,然后用于比较 GetNewBuildingEvents() 返回的每个项目

它是否在每次比较时调用数据库以获取列表?

表达式在 LINQ 中执行时是否枚举参数

如果你想知道迭代了多少次,只需在迭代时执行一些可观察副作用的序列上运行该代码,以便你可以看到它发生了多少次。

可以使用以下帮助程序方法将任何序列包装成一个序列,该序列将在每次迭代时写出到控制台。

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 子句的值,并且不需要多次迭代。