将IQueryable转换为IEnumerable会再次执行查询吗?

时间:2010-10-31 05:17:16

标签: c# linq

在我的查询中,我需要返回IEnumerable,但我不知道此操作是否会使查询再次执行?

var data = Repository<Person>.Find().AsEnumerable();

Find()会返回IQueryable,因为IQueryable会继承IEnumerable。我怀疑AsEnumerable是否重复执行。

我知道 var data = Repository<Person>.Find().ToList()执行查询两次。一个用于Find(),第二个用于Tolist()

3 个答案:

答案 0 :(得分:20)

IQueryable 是IEnumerable。没有转换,因此没有任何工作。

当你明确地或通过调用GetEnumerator()来呼叫foreach时,工作就会发生。

另外,您确认Repository.Find().ToList()两次调用SQL吗?这对我来说听起来不对。

答案 1 :(得分:11)

除了将AsEnumerable运算符应用于IQueryable之外,

as实际上并没有做任何事情。因此,您应用于对象的任何未来方法都将使用System.Linq.Enumerable扩展方法集,而不是System.Linq.Queryable方法。

这都是关于延期执行的。在您尝试枚举之前,没有任何东西会对您的可查询源(可能是数据库)执行任何操作。

换句话说:

var data=Repository.Find().AsEnumerable() 
/* The query is only actually performed AFTER here */  
.ToList();

如果您的代码:

var data=Repository.Find().ToList();

执行查询两次,这是因为你在Find()方法中做了一些不正确的事情,绝对不应该这样。

var data = Respository.Find();

应该执行查询ZERO次。

var result = data.ToList(); // THIS is what should execute the query.

答案 2 :(得分:1)

将linq视为“流”,聚合函数是“Flush”。 “linq to db”流只能刷一次。 .AsEnumerable(),. Where(),....是一种准备查询的方法 .ToList(),.First(),. Max()是一个聚合 但如果你不调用聚合,那么你的linq结果就不会运行了。它只有在枚举时才开始工作。

var result = users.Select(usr => usr.Name);
直到

,才会发生任何事情

称为1聚合

result.First()

或2个结果正在枚举

result.ToList().ForEach(...)

回答你的问题 - .Find(),. AsEnumerable()不是聚合函数