LINQ语句中的.linq asenumerablee 和 AsQueryable的区别

这3个方法的功能完全不同, 应按照具体业务场景使用.
AsQueryable()
先说说什么是 IQueryable
IQueryable 是当前的 data provider 返回的类型. 在本文的例子中都是 EF data provider for sql server, 返回的是一种数据查询结构, 用于生成 sql 语句.
lazy load 特性
以下是一段最常见的代码,
var products = db.Product.where(p =& p.Type == &food&).select(p =& new { p.Id, p.Name, p.CreateTime});
.Select 返回类型为 IQueryable&T&, 语句执行后不会立刻查询数据库, 而是在迭代使用 products 时才会查数据库, 具有 lazy load 的特性, 按需查数据库可提高程序效率.
迭代时上面的代码生成的 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
显式调用 AsQueryable()?
如果对没有继承 IQueryable 接口的类型使用 AsQueryable(), 会转换类型, 如下,
int[] array = new { 1, 2, 4, 5};
var enumArray = array.AsQueryable();
因为 Array 只继承了 IEnumerable, 没有继承 IQueryable, 所以会发生类型转换. 这种情况下使用没有任何作用, 因为 IQueryable 没有声明任何新方法.
本人更多是在单元测试中使用 AsQueryable() 模拟 EF data provider 返回的数据.
其他有用的情况我暂时还没碰到, 请大家指教.
IQueryable的限制
此外 IQueryable 有诸多限制, 只支持数据库查询语法, 无法支持 Linq to object 的操作, 如以下2段代码会在运行时出错,
var products = db.Product
.Where(p =& p.Type == &food&)
.Select(p =& new { p.Id, p.Name, p.CreateTime.Date});
// 如果改成 .Select(p =& new { p.Id, p.Name, DbFunction.TruncateDate(p.CreateTime)})
// 就能正常运行.
var products = db.Product
.Where(p =& p.Type == &food&)
.Select(p =& MyMethod(p));
.Select() 的返回类型为 IQueryable.
第1段代码, 我认为 IQueryable 还不够智能, 无法把 p.CreateTime.Date 转换为 sql 相关的 function, 而使用 DbFunctions 要求使用者了解同时熟悉 linq to entity 及 sql 的内置方法.
第2段代码, 生成 的 sql 无法返回 MyMethod 类型, 是可以理解的.
但是, 对代码加了 AsEnumerable() 后运行正常, 因为 IEnumerable 支持 Linq to object 的操作.
AsEnumerable()
同样支持 lazy load, 但不要滥用
同样是延迟查询, 与 AsQueryable() 区别是, 迭代时遇到 AsEnumerable() 会先进行 sql 查询, 所以对已查出来的结果当然能进行 Linq to object 操作.
但是, 千万不要为了方便而滥用 AsEnumerable(), 可能会严重消耗资源, 如下代码,
var products = db.Product.AsEnumerable()
.Select(p =& new {p.Id, p.Name, p.CreateTime.Date});
上面的代码在查询时会把整个Product表的结果存放进内存, 然后进行 .Select 查询!!!
当我不熟悉 DbFunction 或者 要用自定义返回类型应该怎么办
正确的做法应该如下,
var yourOwnType = db.Product
.Select(p =& new {p.Id, p.Name, p.CreateTime})
.AsEnumerable()
.Select(p =& MyMethod(p));
或者在迭代操作 product 时调用 product.CreateTime.Date
AsEnumerable()的限制
如果你写了以下代码,
var products = db.Product
.Select(p =& new {p.Id, p.Name, p.CreateTime})
.AsEnumerable()
.Select(p =& new {p.Id, p.Name, p.CreateTime.ToString()});
.AsQueryable()
.Where(p=& p.Name == &xxx&);
那么最后的 .Where()永远不会执行!!!
因为在使用 AsQueryable().Where() 要求 Linq to entity 进行数据库查询, 但是第一次 AsEnumerable() 时已经进行了数据库查询并且断开连接, 并且查询结果已经作为实实在在的 object, 对 object 不可能再次使用 AsQueryable().Where() 叠加数据库查询!
调用 ToList() 会立刻查询并保存结果, 而不会等到迭代时才查询. 作用和 lazy load 是对立的.
在需要得到完整结果后, 再处理的场景, 需要使用 ToList().
例如, 在返回mvc ActionResult 的时候, 要先使用 ToList(), 再作为 model 传给 view. 不知道 mvc 是出于什么考虑不支持在生成 html 的时候lazy load, 请大家指教!
有错的地方请大家指出, 欢迎拍砖.
参考 StackOverflow:
对博客园的 markdown 解析器无语了, 显示效果大打折扣
阅读(...) 评论()您的位置: >
linq中AsEnumerable和AsQueryable的区别
学习标签:
本文导读:用Linq来操作集合的时候会用到AsQueryable()和AsEnumerable(),何时该用AsQueryable()和何时该用AsEnumerable(),或许存在些疑惑。AsQueryable是在数据库中查询再返回数据,AsEnumerable是从数据库读取全部数据再在程序中查询。
在使用LINQ 进行数据集操作时,LINQ 不能直接从数据集对象中查询,因为数据集对象不支持LINQ 查询,所以需要使用AsEnumerable 方法返回一个泛型的对象以支持LINQ 的查询操作。
C# 代码 &&复制
string strcon = &Data Source=.\SQLEXPRESS;Initial Catalog=Db_EPersist Security Info=TUser ID=Password=sa&;
SqlConnection con = new SqlConnection(strcon);
con.Open();
string strsql = &select * from SC,Course o&;
SqlDataAdapter da = new SqlDataAdapter(strsql,con);
DataSet ds = new DataSet();
da.Fill(ds, &mytable&);
DataTable tables=ds.Tables[&mytable&]; //创建表
var dslp = from d in tables.AsEnumerable()//执行LINQ语句,这里的.AsEnumerable()是延迟发生,不会立即执行,实际上什么都没有发生
foreach(var res in dslp)
Response.Write(res.Field&string&(&Cname&).ToString());
一、linq中AsEnumerable和AsQueryable的区别
1、AsEnumerable()是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First, Single, ToList....的时候)才执行。
2、AsEnumerable将一个序列向上转换为一个IEnumerable, 强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。
3、AsQueryable将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装。
4、AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。
5、ToList()立即执行
6、当你需要操作结果的时候,用.ToList(),否则,如果仅仅是用来查询不需要进一步使用结果集,并可以延迟执行,就用.AsEnumerable()/IEnumerable /IQueryable
7、AsEnumerable()虽然延迟执行,但还是访问数据库,而.ToList()直接取得结果放在内存中。比如我们需要显示两个部门的员工时,部门可以先取出放置在List中,然后再依次取出各个部门的员工,这时访问的效率要高一些,因为不需要每次都访问数据库去取出部门。
8、IQueryable实现了IEnumberable接口。但IEnumerable&T& 换成IQueryable&T&后速度提高很多。
9、IQueryable接口与IEnumberable接口的区别:& IEnumerable&T& 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable&T& 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
10、IEnumerable跑的是Linq to Object,强制从数据库中读取所有数据到内存先。
二、AsEnumerable和AsQueryable的实例
C# 代码 &&复制
using (testContext context = new testContext())
var query = (from item in context.Users.AsQueryable()
where item.id & <span style="color: #
select item.id).ToList();
var query2 = (from item in context.Users.AsEnumerable()
where item.id & <span style="color: #
select item.id).ToList();
服务器端sql
SQL 代码 &&复制
--AsQueryable
[Extent1].[id] AS [id]
FROM [dbo].[User] AS [Extent1]
Where [Extent1].[id] & <span style="font-weight: color: #
--AsEnumerable
[Extent1].[id] AS [id],
[Extent1].[usn] AS [usn],
[Extent1].[pwd] AS [pwd],
[Extent1].[created] AS [created]
FROM [dbo].[User] AS [Extent1]
C# 代码 &&复制
using (testContext context = new testContext())
var query = (from item in context.Users.AsQueryable()
where item.id & <span style="color: #
orderby item.id ascending
select item.id).Skip(<span style="color: #).Take(<span style="color: #).ToList();
var query2 = (from item in context.Users.AsEnumerable()
where item.id & <span style="color: #
orderby item.id ascending
select item.id).Skip(<span style="color: #).Take(<span style="color: #).ToList();
服务器端sql
SQL 代码 &&复制
--AsQueryable
Select TOP (<span style="font-weight: color: #)
[Filter1].[id] AS [id]
FROM ( Select [Extent1].[id] AS [id], row_number() OVER (ORDER BY [Extent1].[id] ASC) AS [row_number]
FROM [dbo].[User] AS [Extent1]
Where [Extent1].[id] & <span style="font-weight: color: #
AS [Filter1]
Where [Filter1].[row_number] & <span style="font-weight: color: #
orDER BY [Filter1].[id] ASC
--AsEnumerable
[Extent1].[id] AS [id],
[Extent1].[usn] AS [usn],
[Extent1].[pwd] AS [pwd],
[Extent1].[created] AS [created]
FROM [dbo].[User] AS [Extent1]
您可能感兴趣
一月好评排行榜LINQ语句中的.AsEnumerable()&和&.AsQueryable()的区别
在写LINQ语句的时候,往往会看到.AsEnumerable()
和 .AsQueryable() 。
string strcon = "Data Source=.\\SQLEXPRESS;Initial Catalog=Db_EPersist Security Info=TUser ID=Password=sa";
SqlConnection con = new SqlConnection(strcon);
con.Open();string strsql = "select * from SC,Course o";
SqlDataAdapter da = new SqlDataAdapter(strsql,con);
DataSet ds = new DataSet();
da.Fill(ds, "mytable");
DataTable tables=ds.Tables["mytable"]; //创建表var dslp = from d in tables.AsEnumerable()//执行LINQ语句,这里的.AsEnumerable()是延迟发生,不会立即执行,实际上什么都没有发生foreach(var res in dslp)
Response.Write(res.Field&&/SPAN&string&("Cname").ToString());
上述代码使用LINQ 针对数据集中的数据进行筛选和整理,同样能够以一种面向对象的思想进行数据集中数据的筛选。在使用LINQ
进行数据集操作时,LINQ 不能直接从数据集对象中查询,因为数据集对象不支持LINQ 查询,所以需要使用AsEnumerable
方法返回一个泛型的对象以支持LINQ 的查询操作。
.AsEnumerable()是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First,
Single, ToList....的时候)才执行。
下面就是.AsEnumerable()与相对应的.AsQueryable()的区别:
AsEnumerable将一个序列向上转换为一个IEnumerable,
强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。
AsQueryable将一个序列向下转换为一个IQueryable,
它生成了一个本地查询的IQueryable包装。
.AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。
.ToList()立即执行
当你需要操作结果的时候,用.ToList(),否则,如果仅仅是用来查询不需要进一步使用结果集,并可以延迟执行,就用.AsEnumerable()/IEnumerable&/IQueryable
.AsEnumerable()虽然延迟执行,但还是访问数据库,而.ToList()直接取得结果放在内存中。比如我们需要显示两个部门的员工时,部门可以先取出放置在List中,然后再依次取出各个部门的员工,这时访问的效率要高一些,因为不需要每次都访问数据库去取出部门。
IQueryable实现了IEnumberable接口。但IEnumerable
换成IQueryable后速度提高很多。原因:
IQueryable接口与IEnumberable接口的区别:&
IEnumerable 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable
是将Skip ,take
这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
IEnumerable跑的是Linq
to Object,强制从数据库中读取所有数据到内存先。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。下次自动登录
现在的位置:
& 综合 & 正文
LINQ语句中的.AsEnumerable() 和 .AsQueryable()的区别
在写LINQ语句的时候,往往会看到.AsEnumerable() 和 .AsQueryable() 。例如:
string strcon = "Data Source=.\\SQLEXPRESS;Initial Catalog=Db_EPersist Security Info=TUser ID=Password=sa";SqlConnection con = new SqlConnection(strcon);con.Open();string strsql = "select * from SC,Course o";SqlDataAdapter da = new SqlDataAdapter(strsql,con);DataSet ds = new DataSet();da.Fill(ds, "mytable");DataTable tables=ds.Tables["mytable"]; //创建表var dslp = from d in tables.AsEnumerable()//执行LINQ语句,这里的.AsEnumerable()是延迟发生,不会立即执行,实际上什么都没有发生foreach(var res in dslp)
Response.Write(res.Field&string&("Cname").ToString());}
上述使用LINQ 针对数据集中的数据进行筛选和整理,同样能够以一种面向对象的思想进行数据集中数据的筛选。在使用LINQ 进行数据集操作时,LINQ 不能直接从数据集对象中查询,因为数据集对象不支持LINQ 查询,所以需要使用AsEnumerable 方法返回一个泛型的对象以支持LINQ 的查询操作。
.AsEnumerable()是延迟执行的,实际上什么都没有发生,当真正使用对象的时候(例如调用:First, Single, ToList....的时候)才执行。下面就是.AsEnumerable()与相对应的.AsQueryable()的区别:AsEnumerable将一个序列向上转换为一个IEnumerable, 强制将Enumerable类下面的查询操作符绑定到后续的子查询当中。AsQueryable将一个序列向下转换为一个IQueryable, 它生成了一个本地查询的IQueryable包装。
.AsEnumerable()延迟执行,不会立即执行。当你调用.AsEnumerable()的时候,实际上什么都没有发生。
.ToList()立即执行
当你需要操作结果的时候,用.ToList(),否则,如果仅仅是用来查询不需要进一步使用结果集,并可以延迟执行,就用.AsEnumerable()/IEnumerable /IQueryable
.AsEnumerable()虽然延迟执行,但还是访问数据库,而.ToList()直接取得结果放在内存中。比如我们需要显示两个部门的员工时,部门可以先取出放置在List中,然后再依次取出各个部门的员工,这时访问的效率要高一些,因为不需要每次都访问数据库去取出部门。
IQueryable实现了IEnumberable接口。但IEnumerable&T& 换成IQueryable&T&后速度提高很多。原因:
IQueryable接口与IEnumberable接口的区别:
IEnumerable&T& 泛型类在调用自己的SKip 和 Take 等扩展方法之前数据就已经加载在本地内存里了,而IQueryable&T& 是将Skip ,take 这些方法表达式翻译成T-SQL语句之后再向SQL服务器发送命令,它并不是把所有数据都加载到内存里来才进行条件过滤。
IEnumerable跑的是Linq to Object,强制从数据库中读取所有数据到内存先。
&&&&推荐文章:
【上篇】【下篇】

我要回帖

更多关于 linq asqueryable 的文章

 

随机推荐