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

C# 表达式在LINQ中执行时是否枚举参数?,c#,.net,linq,C#,.net,Linq,我有一个使用LINQ返回IQueryable的方法 return eventFacade.GetNewBuildingEvents() .Where(EventPredicates.IsBuildingOwner( memberFacade.GetFriendsAndColleagues(m).Select(y => y.Id)) ) getFriendsandColleguesm.Selec

我有一个使用LINQ返回IQueryable的方法

 return eventFacade.GetNewBuildingEvents()
                .Where(EventPredicates.IsBuildingOwner(
                       memberFacade.GetFriendsAndColleagues(m).Select(y => y.Id))
        )
getFriendsandColleguesm.Selecty=>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进行过滤在数据库中进行,而IEnumerable在内存中进行

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

因此,在执行最终查询时,传递到表达式中的IEnumerable是否枚举一次,然后用于比较GetNewBuildingEvents返回的每个项


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

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

您可以使用以下helper方法将任何序列包装成一个序列,该序列将在每次迭代时写入控制台

public static IEnumerable<T> NoisyWrapper<T>(IEnumerable<T> source)
{
    Console.WriteLine("Rabble rabble rabble!!!");
    foreach (var item in source)
        yield return item;
}
这样就解决了一般情况下的问题


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

GetNewBuildingEvents的实现和返回类型是什么?什么是IQueryable提供者?无论如何,我相信或它是LINQ to entities或IQueryable将引发异常。我在查询中使用.AsEnumerable,并在稍后的方法中将其转换为另一个对象。上面写的查询编译并运行得很好,您是专门询问关于Linq到SQL/DB的,对吗?因为AFAIK可以对LINQ to对象以及LINQ to DB使用IQueryable和IEnumerable。最终实际运行的内容取决于LINQ提供程序。只需在SQL中附加一个探查器,即可查看发送的确切查询。如果您和/或您的DB管理员对结果查询感到满意,那么就接受它们。如果没有,您可以开始考虑对它们进行优化。@MattFoxxDuncan重点是查看从这个C代码生成的SQL查询,而不是查看它运行了多长时间。这将帮助您确定哪些操作成功映射到SQL,哪些操作映射到SQL效率低下,哪些操作根本没有映射到SQL,哪些操作是在客户端完成的。太棒了!谢谢,这正是我想要的解释。