我有一个使用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
过滤,而IEnumerable
则在内存中进行。
我也知道,在迭代集合的情况下,最好枚举集合,以便每次迭代都不会调用数据库。
因此,当执行我的最终查询时,传递到我的表达式中的IEnumerable
会被枚举一次,然后用于比较GetNewBuildingEvents()
或
是否在每次比较时调用数据库以获取列表?
答案 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
子句的值,并且不应该多次迭代。