IEnumerable<T> 和 IQueryable<T> 澄清?

Posted

技术标签:

【中文标题】IEnumerable<T> 和 IQueryable<T> 澄清?【英文标题】:IEnumerable<T> and IQueryable<T> clarification? 【发布时间】:2012-06-23 09:02:17 【问题描述】:

看完this的问题, 我需要澄清一些事情。

IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;

问题:

1) 可以这样说:在第一个查询中,SQLServer 正在运行整个操作,包括 where 子句并返回 ONLY 相关行 - 而第二个查询则执行 SELECT * .. . 并将 所有 行返回到 C# 和 THEN 过滤器中?

2) 如果我只有一个 集合 - 在内存中怎么办。 (var lstMyPerson = new List&lt;MyPerson&gt;())

IQueryable<MyPerson> lst = from c in lstMyPerson 
where c.City == "<City>"
select c;

IEnumerable<MyPerson> custs = from c in lstMyPerson 
where c.City == "<City>"
select c;

现在执行会有什么不同?

【问题讨论】:

看看这个相关主题:***.com/questions/252785/…。而且,您在#1中的假设是正确的。不是 100% 确定 #2,所以我会把它留给另一个人。 @blizz 我已经读过了。所有答案都来自一本书 POV。那里没有回答我的问题.... :(...我会很高兴看看哪一行回答了我的问题 【参考方案1】:

1:不,不正确

由于您只是将结果存储IEnumerable&lt;Customer&gt;,但仍然具有产生结果的完全相同的表达式,因此它们都将在服务器上执行并仅返回相关行。

你会得到不同的行为:

IEnumerable<Customer> custs = from c in (IEnumerable<Customer>)db.Customers
    where c. City == "<City>"
    select c;

在这种情况下,您将强制将 db.Customers 集合用作 IEnumerable&lt;T&gt;,在枚举时将获取整个集合。

请注意:

IEnumerable<Customer> x = from c in db.Customers
                          where c.City == "<City>"
                          select c;

和这个不一样:

IEnumerable<Customer> x = from c in db.Customers
                          select c;
IEnumerable<Customer> y = x.Where(c => c.City == "<City>");

在第一种情况下,where 子句将成为 SQL 的一部分,而在第二种情况下则不会。这就是为什么链接的问题/答案涉及差异,而您的代码没有。

还请注意,只有您编写的语句实际上不会在服务器上执行任何操作,因为它们实际上只会存储惰性集合。如果您继续枚举这些集合,届时相关位将在服务器上执行。

2:List&lt;T&gt; 没有实现或具有IQueryable&lt;T&gt; 的扩展方法,所涉及的 LINQ 运算符也不会返回与 IQueryable&lt;T&gt; 兼容的任何内容

在这种情况下,第一个不会编译。

【讨论】:

不,正如我所说,他们都会这样做。但是,在链接代码的情况下,Where LINQ 运算符应用于IEnumerable&lt;T&gt;IQueryable&lt;T&gt;,您已将where 子句添加到原始查询。这会更改操作的顺序,因此在您的情况下,它们将以相同的方式执行。在链接的答案中,他们不会。 关于强制将 db.Customers 集合用作 IEnumerable,枚举时将获取整个集合,如果我理解正确,此代码将得到 ALL客户然后过滤? 正确,就是这样。 @LasseV.Karlsen 你好。 (过了一会儿...)在您的3'rd 代码示例中:第一行实际上并没有从数据库中获取数据。播种为什么下一行不能只添加where 子句? (所以在枚举整个查询时将被发送到数据库)?这种行为是因为第一行使用Ienumerable 还是因为第二行使用Ienumerable 或者因为x.where 抱歉回复晚了。原因是编译器不再知道该集合是可以查询的。这意味着由于集合已存储到IEnumerable&lt;Customer&gt;IQueryable&lt;T&gt; 运算符不再可用。因此,答案中的最后一个分配将生成另一个惰性集合,但是这个集合在枚举完时会首先从数据库中获取每个客户,然后在内存中进行过滤。

以上是关于IEnumerable<T> 和 IQueryable<T> 澄清?的主要内容,如果未能解决你的问题,请参考以下文章

IEnumerable<T>是啥意思?

将 IEnumerable<Ienumerable<T>> 转换为 Dictionary<key,IEnumerable<T>>

IQueryable 和 IEnumerable

如何将两个 IEnumerable<T> 连接成一个新的 IEnumerable<T>?

List<T> 派生自 IList<T> 和 IEnumerable<T>,没用?

无法将类型“IEnumerable<T>”隐式转换为“ActionResult<IEnumerable<T>>”