欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

IQueryable和IEnumerable以及AsEnumerable()和ToList()的区别

程序员文章站 2022-09-24 11:21:32
注意:本文背景为 Linq to sql 。文中ie指代IEnumerable,iq指代IQueryable。 IQueryable 和 IEnumerable 的区别 IQueryable延时执行;扩展方法接受的是Expression(必须要能转成sql,否则报错) IEnumerable延时执行 ......

注意:本文背景为 linq to sql 。文中ie指代ienumerableiq指代iqueryable

iqueryable 和 ienumerable 的区别

  • iqueryable
    延时执行;扩展方法接受的是expression(必须要能转成sql,否则报错)

  • ienumerable
    延时执行;扩展方法接受的是func(c#语法)

asenumerable() 和 tolist() 的区别

  • tolist()
    立即执行,加载数据到内存中。

  • asenumerable()
    延迟执行,真正使用时才加载数据。
    对iqueryable对象使用asenumerable()后,仍然是延迟执行,不过此时对象本质已经变了。
    前面已经说了ienumerable的扩展方法接受的是func(c#语法),当ie对象(iq转变)真正使用时,会有2个步骤:
    1.它会把iq对象(转变之前的)的扩展方法翻译成sql语句,查询出数据加载到内存中,变为ie对象;
    2.此时再把ie对象(转变之后的)的扩展方法,使用c#求解,得到最终结果。
    例如:iq对象的skip、take方法,会被翻译成sql,在数据库里执行取出最终结果。
    而ie对象的skip、take方法,则会取出全部数据到内存中,在内存中执行skip、take,会耗费大量资源。

误区

  • 误区1:对 iq对象 和 ie对象 使用foreach时,对于循环的每项都要查询数据库。

    错误!
    foreach针对的是数据集整体对象(枚举器?)。当使用foreach时,不管是iq对象还是ie对象,它们都是查询数据库一次,然后开始循环,直至循环结束。不过,当后续再次使用iq对象或ie对象的具体数据时,它们仍然会再次查询数据库。

结论

假设我们把最终数据之前的数据称为中间数据,那么:

  1. 中间数据只是作为条件筛选,需要的只是层层筛选之后的最终数据时,应该继续使用iqueryable,防止加载不必要的数据到内存中。
  2. 存在中间数据,且中间数据被重复使用时,应该使用iqueryable.tolist()立即加载到内存里使用(都被重复使用了,应该叫做最终数据了吧..);
  3. 如果中间结果无用,且想对iqueryable对象使用func(c#语法)的扩展方法,应该使用iqueryable.asenumerable()转成ienumerable对象,进行后续操作。

参考

  1. linq查询中的ienumerable<t>和iqueryable<t>
  2. linq使用细节之.asenumerable()和.tolist()的区别
  3. 建议29:区别linq查询中的ienumerable<t>和iqueryable<t> - 陆敏技《编写高质量代码改善c#程序的157个建议》