linq初级问题,请解答下

wctmac123 2020-06-22 04:56:57
本人初学linq,有个地方不明白,.ToList()和AsEnumerable(),按照文档上来说 .ToList是直接执行,AsEnumerable是延迟执行,其实没任何意义,只有要使用结果集的时候才会查询数据库,如果不需要使用结果集,并且要延迟的i情况下可以使用AsEnumerable,我有个疑问,一般查询不是都要用到结果集么,那么AsEnumerable的使用场景是不是很少呢,能不能举例几个AsEnumerable的使用场景,可以让我更加的形象了解AsEnumerable具体适合哪些地方用
...全文
1725 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
wctmac123 2020-06-23
  • 打赏
  • 举报
回复
引用 7 楼 以专业开发人员为伍 的回复:
这就有点“八股”了。 ToList 是返回 List<>类型,这个类型有着复杂的一大堆内容,非常非常复杂,细节许多。要实现它就必须将查询发送到数据库去,将结果取过来,然后将结果缓存到 List<> 结构中。如果有 n个地方用到了 ToList 的结果对象,那么其实也仅仅查询数据库一次。 AsEnumerable 是返回可枚举的接口类型,是非常简单非常轻的接口,可能只有 ToList 的百分之一而已,没有额外的细节要求。要实现这个接口就可以仅仅保存编译好查询规划,然后当读取数据时一遍遍地“重复地”将查询发送到数据库去,一遍遍地重复取结果过来。这样的好处当然是推迟到真正读取数据的时候才发送查询语句,如果不走到延迟的最后一步而提前结束了,那么就无需真正去数据库查询了。坏处当然就是如果有n个地方都用到了 AsEnumerable 的结果对象,那么其实是反复查询了数据库 n 次。
了解
threenewbee 2020-06-23
  • 打赏
  • 举报
回复
如果provider支持服务器游标的话,那么asenumerable占用内存更少。
  • 打赏
  • 举报
回复
我说“八股”的实际意思是,其实类似 AsEnumerable 这类所要表达是一类设计模式,而不是具体实现。所以理解二者的差别等多地是要从一种文档的规范制定者的角度去理解,切不可从最低级的工程师的角度去理解。

可以肯定地说,有不少不同框架 provider 具体实现某种类型业务对象的 AsEnumerable 封装功能时,可能直接返回 ToList 结果,或者是直接把数据装载在内存缓存里,然后返回。但是软件的“是非”是以测试为准的,只要是人家对于 AsEnumerable 的实现(暂时地)让你测试通过了,给了你要的数据结果,那么可能你也就暂时不用去纠结 AsEnumerable 和 ToList 的区别了。你所要坚持的只能是这两个东西在“期望上的”区别,而不能八股地认为这种区别是死的东西预先写好的。真正这两个区别是接口设计者——.net框架设计总工程师以及一些.net框架书籍传播者——给出来的正确理念,仅仅是理念,希望大家都以此为合同(接口)来实现各类 AsEnumerable 实现,而不是死要求。
  • 打赏
  • 举报
回复
如果仅仅查询一次,那么使用 AsEnumerable 则可以得到一个“轻量级”的结果,那么程序的任意流程如果没有走到实际读取查询结果的地步时,就等于是没有花费普通c#代码几万倍的性能代价去读取和序列化数据库了。

而假设你认为代码根本不可能走不到实际读取查询结果的地步,那么你自然可以使用 ToList 也可以使用 AsEnumerable ,没有什么差别。

所以正面思考可以理解,而一味地反过来思考问题,反而是过于较真儿这种差别了。
  • 打赏
  • 举报
回复
这就有点“八股”了。

ToList 是返回 List<>类型,这个类型有着复杂的一大堆内容,非常非常复杂,细节许多。要实现它就必须将查询发送到数据库去,将结果取过来,然后将结果缓存到 List<> 结构中。如果有 n个地方用到了 ToList 的结果对象,那么其实也仅仅查询数据库一次。

AsEnumerable 是返回可枚举的接口类型,是非常简单非常轻的接口,可能只有 ToList 的百分之一而已,没有额外的细节要求。要实现这个接口就可以仅仅保存编译好查询规划,然后当读取数据时一遍遍地“重复地”将查询发送到数据库去,一遍遍地重复取结果过来。这样的好处当然是推迟到真正读取数据的时候才发送查询语句,如果不走到延迟的最后一步而提前结束了,那么就无需真正去数据库查询了。坏处当然就是如果有n个地方都用到了 AsEnumerable 的结果对象,那么其实是反复查询了数据库 n 次。
圣殿骑士18 2020-06-22
  • 打赏
  • 举报
回复
给你一个必须用IEnumerator的场景,就是微软的类库中,有大量的使用,或者说,你追求写自己写“高性能”类库时,也必须用IEnumerator,而不是List。 为什么?因为使用迭代器,可以最高效的遍历列表,也就是用多少取多少,而不是全部装载到一个新的List里来用(假设你要取一个结果集最多可能有100万个项,你是全装载到List,还是随用随取,更省资源)。 结合yield理解下IEnumerator https://www.cnblogs.com/blueberryzzz/p/8678700.html
正怒月神 2020-06-22
  • 打赏
  • 举报
回复
我想,你可能讨论的延迟,和我理解的稍有不同。
ToList,First(),FirstOrdefault,take。。。。,是把数据加载到本地。

你在没有执行时如上方法时,的确不会装载到内存里。
正怒月神 2020-06-22
  • 打赏
  • 举报
回复
MSDN上也说的比较清晰。 当你使用 where时,传入Expression<Func>表达式树,就如我上面的IQueryable<>一样,组装sql语句。 当你不需要,则转为AsEnumerable。他不是拼接表达式树的,而是直接调用本地方法,对内存里的数据进行筛选。
正怒月神 2020-06-22
  • 打赏
  • 举报
回复
引用 2 楼 wctmac123 的回复:
谢谢大佬回答,场景了解了,但是我看了很多文章都说AsEnumerable是延时的,我有点懵,不知道哪个是对的了 https://www.cnblogs.com/cqj98k/p/10092067.html https://www.cnblogs.com/Mainz/archive/2011/04/08/2009485.html
你可以自己通过ef创建数据库映射,然后测试一下。 这是我当初的测试片段 对应的产生如下2个sql语句。 AsEnumerable比较明显的是,全表缓存。之后才在内存里筛选数据
wctmac123 2020-06-22
  • 打赏
  • 举报
回复
引用 1 楼 正怒月神 的回复:
你应该搞错了。 AsQueryable 是延时的 AsEnumerable 是及时的 https://blog.csdn.net/hanjun0612/article/details/50070081 另外,延迟加载的场景。 假设有一个User表,它有个关联表 Address。 你要显示User信息,但Address是不要显示。 所以他可以是延时的。 只有用到了,才会去加载。没用到,就不加载。
谢谢大佬回答,场景了解了,但是我看了很多文章都说AsEnumerable是延时的,我有点懵,不知道哪个是对的了 https://www.cnblogs.com/cqj98k/p/10092067.html https://www.cnblogs.com/Mainz/archive/2011/04/08/2009485.html
正怒月神 2020-06-22
  • 打赏
  • 举报
回复
你应该搞错了。 AsQueryable 是延时的 AsEnumerable 是及时的 https://blog.csdn.net/hanjun0612/article/details/50070081 另外,延迟加载的场景。 假设有一个User表,它有个关联表 Address。 你要显示User信息,但Address是不要显示。 所以他可以是延时的。 只有用到了,才会去加载。没用到,就不加载。

8,497

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 LINQ
社区管理员
  • LINQ
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧