当前位置: 移动技术网 > IT编程>开发语言>.net > Linq中 AsQueryable(), AsEnumerable()和ToList()的区别和用法

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

2018年12月10日  | 移动技术网IT编程  | 我要评论

女客梦中惊醒,博富定律,hercyna

linq中 asqueryable(), asenumerable()和tolist()的区别和用法:
在写linq语句的时候,往往会看到asenumerable() ,asqueryable() 和tolist()的用法,三者有何区别呢?以下是我的理解,有毛病请大家指教!
在system.linq命名空间下,有两个静态类:
enumerable类,它针对继承了ienumerable<t>接口的集合进行扩展;
queryable类,针对继承了iqueryable<t>接口的集合进行扩展。
一、asqueryable():
先说说什么是 iqueryable,asqueryable将一个序列向下转换为一个iqueryable, 它生成了一个本地查询的iqueryable包装。
1,lazy 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 createtime
iqueryable 有诸多限制, 只支持数据库查询语法, 无法支持 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()。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网