4

我有一个返回IQueryableusing LINQ的方法

 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推迟执行,并且我知道在数据库中进行过滤IQueryableIEnumerable在内存中进行。

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

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

或者

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

4

1 回答 1

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 的查询提供程序将被转换为INSQL 中的子句。IEnumerablewill 需要迭代一次以提供子句的值,IN并且它不应该被迭代多次。

于 2013-09-26T20:28:13.397 回答