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

时间:2013-09-26 20:06:56

标签: c# .net linq

我有一个使用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过滤,而IEnumerable则在内存中进行。

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

因此,当执行我的最终查询时,传递到我的表达式中的IEnumerable会被枚举一次,然后用于比较GetNewBuildingEvents()

返回的每个项目

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

1 个答案:

答案 0 :(得分:3)

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

您可以使用以下帮助器方法将任何序列包装成一个序列,每次序列迭代时都会写入控制台。

public static IEnumerable<T> NoisyWrapper<T>(IEnumerable<T> source)
{
    Console.WriteLine("Rabble rabble rabble!!!");
    foreach (var item in source)
        yield return item;
}

这样就解决了一般情况下的问题。

在特定情况下,序列应仅迭代一次。您正在创建一个表达式,该表达式已编译为数据库查询并在数据库端执行。在Contains中使用IEnumerable与大多数基于SQL的查询提供程序在适当的上下文(您的)中将被转换为SQL中的IN子句。 IEnumerable需要迭代一次才能提供IN子句的值,并且不应该多次迭代。