Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法

发布日期:2019-01-27
Linq中 AsQueryable() AsEnumerable()和ToList()的区别和用法:在写LINQ语句的时候,往往会看到AsEnumerable() ,AsQueryable() 和ToList()的用法,三者有何区别呢?以下是我的理解,有毛病请大家指教!在System.Linq命名空间下,有两个静态类:Enumerable类,它针对继承了IEnumerable<T>接口的集合进行扩展;Queryable类,针对继承了IQueryable<T>接口的集合进行扩展。一、AsQueryable():先说说什么是 IQueryableAsQueryable将一个序列向下转换为一个IQueryable 它生成了一个本地查询的IQueryable包装。1lazy load 特性以下是一段最常见的代码:var products = db.Product.where(p => p.Type == "food").select(p => new { p.Id p.Name p.CreateTime})注意:Select() 的返回类型为 IQueryable,为 IQueryable<T> 语句执行后不会立刻查询数据库 而是在迭代使用 products 时才会查数据库 具有 lazy load 的特性 按需查数据库可提高程序效率。2高程序效率.迭代时上面的代码类似于下面的 sql 语句:select Id Name CreateTime from Product where Type = "food"对 products 再次使用数据库查询操作 运行时会把结果合并为1条 sql 语句 如下var products = db.Product.where(p => p.Type == "food").select(p => new { p.Id p.Name p.CreateTime})var orderedProducts = products.OrderBy(p => p.CreateTime)迭代时生成的 sql 语句类似:select Id Name CreateTime from Product where Type = "food" order by CreateTimeIQueryable 有诸多限制 只支持数据库查询语法 无法支持 Linq to object 的操作, 是LINQ TO SQL。结论:AsQueryable将一个序列向下转换为一个IQueryable 它生成了一个本地查询的IQueryable包装。 二、AsEnumerable()同样支持 lazy load是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First Single ToList....的时候)才执行。 但不要滥用。迭代时遇到 AsEnumerable() 会先进行 sql 查询 但是 千万不要为了方便而滥用 AsEnumerable() 可能会严重消耗资源能进行 Linq to object 操作。eg:var products = db.Product.AsEnumerable().Select(p => new {p.Id p.Name p.CreateTime.Date})对IQueryable对象使用AsEnumerable()后,仍然是延迟执行,不过此时对象本质已经变了。上面的代码在查询时会把整个Product表的结果存放进内存 然后进行 .Select 查询,严重消耗资源。结论:AsEnumerable将一个序列向上转换为一个IEnumerable 强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。 注意:IQueryable实现了IEnumberable接口。但IEnumerable<T> 换成IQueryable<T>后速度提高很多。IQueryable接口与IEnumberable接口的区别:  IEnumerable<T> 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable<T> 是将Skip take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。 三、ToList()调用 ToList() 会立刻查询并保存结果 而不会等到迭代时才查询,作用和 lazy load 是相反的。在需要得到完整结果后 再处理的场景 需要使用 ToList()。