咨询区
stackoverflowuser:
请问类型 IQueryable<T> 和 IEnumerable<T> 有什么异同?我应该使用哪一个而不是另一个,代码如下:
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;我知道这两者都是延迟执行,我应该如何选择?
回答区
Kasper Roma:
是的,两者都是延迟执行,我来用 SQL Server profiler 来演示两者的不同,考虑下面的代码:
MarketDevEntities db = new MarketDevEntities();IEnumerable<WebLog> first = db.WebLogs;
var second = first.Where(c => c.DurationSeconds > 10);
var third = second.Where(c => c.WebLogID > 100);
var result = third.Where(c => c.EmailAddress.Length > 11);Console.Write(result.First().UserName);在 SQL Server profiler 中我捕获到了如下的sql。
"SELECT * FROM [dbo].[WebLog]"这张表中大概有 100w 条记录,sql花费了大概 90s, 显而易见,代码首先会将 WebLog,也 就是将所有的表记录全部灌入到内存中,然后依次使用 Where() 在内存中进行过滤。
接下来用 IQueryable 替代 IEnumerable, 再次观察一下 SQL Server profiler,可以捕获如下sql。
"SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"这个 sql 大概花费了 4s。
IQueryable 中有一个 Expression 属性,它存储着 表达式树,它的完整构建在于 result 变量处(这里是延迟执行),当真正执行的时候,这个 表达式树 会被解析成 sql 到数据库中执行。
点评区
Kasper Roma 大佬说的是有理有节,图文并茂,一看就懂,大写的????????,我还真的特意看了下有没有 Expression 属性 ????????????
//// Summary:// Provides functionality to evaluate queries against a specific data source wherein// the type of the data is not specified.public interface IQueryable : IEnumerable{//// Summary:// Gets the type of the element(s) that are returned when the expression tree associated// with this instance of System.Linq.IQueryable is executed.//// Returns:// A System.Type that represents the type of the element(s) that are returned when// the expression tree associated with this object is executed.Type ElementType { get; }//// Summary:// Gets the expression tree that is associated with the instance of System.Linq.IQueryable.//// Returns:// The System.Linq.Expressions.Expression that is associated with this instance// of System.Linq.IQueryable.Expression Expression { get; }//// Summary:// Gets the query provider that is associated with this data source.//// Returns:// The System.Linq.IQueryProvider that is associated with this data source.IQueryProvider Provider { get; }}原文链接:https://stackoverflow.com/questions/2876616/returning-ienumerablet-vs-iqueryablet