码迷,mamicode.com
首页 > 编程语言 > 详细

IEnumerable<T>和IQueryable<T>区分

时间:2018-06-06 01:04:22      阅读:168      评论:0      收藏:0      [点我收藏+]

标签:csdn   arp   为我   http   tar   运行   object   数据库   排序   

哎,看了那么多,这个知识点还是得开一个文章

IQueryable和IEnumerable都是延时执行(Deferred Execution)的,而IList是即时执行(Eager Execution)

IQueryable和IEnumerable在每次执行时都必须连接数据库读取而IList读取一次后,以后各次都不需连接数据库。

前两者很容易造成重复读取,性能低下,并且可能引发数据不一致性

IQueryable弊端:当把查询出来的数据,根据指定条件添加到其他表中时,会报连接以打开错误!原因:IQueryable在每次执行时都必须连接数据库读取,所以数据库连接是一直开着的!

 

LINQ查询方法一共提供了两类扩展方法,在System.Linq命名空间下,有两个静态类:

    Enumerable类,它针对继承了IEnumerable<T>接口的集合类进行扩展。

    Queryable类,它针对继承了IQueryable<T>接口的集合类进行扩展。

接口IQueryable<T>实际也是继承了IEnumerable<T>接口的,简单的来表述就是:本地数据源用IEnumerable<T>,远程数据源用IQueryable<T>。

LINQ查询从功能上来讲实际上可以分为三类:LINQ to OBJECTS、LINQ to  SQL、LINQ to XML。设计Enumerable<T>和Queryable<T>两套接口的原因是为了区别对待LINQ to OBJECTS、LINQ to SQL,

针对LINQ to OBJECTS时,使用Enumerable中的扩展方法对本地集合进行排序和查询等操作,查询参数接受的是Func<>。

针对LINQ to SQL时,则使用Queryable中的扩展方法,它接受的参数是Expression<>。

LINQ to SQL引擎最终会将表达式树转化成为相应的SQL语句,然后在数据库中执行。//表达式树???啥jb

 

原文
在使用EF查询数据的时候,我们常用的查询数据方式有linq to sql,linq to object,
查询返回的结果有两种类型:IQueryable、IEnumerable,两者内部的处理机制是完全不同的。
在System.linq命名空间,有两个静态类:Queryable和Enumerable.

在System.linq.Queryable中,参数接收的是一个表达式类型,返回IQueryable接口
public static IQueryable<TSource> Where<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate);
在System.linq.Enumerable中,参数接收的是一个谓词表达式,也就是一个委托
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);  
那么在查询数据使用linq to object的时候,会根据传递的参数不同返回不同的类型. 
1.where条件接收表达式,返回IQueryable接口
技术分享图片

2.where条件接收一个谓词表达式(委托)返回一个IEnumerable接口

技术分享图片

那么什么时候用IQueryable<T>,什么时候用IEnumerable<T>?

1.Expression是一个表达式,会存储拼接表达式树,直到在运行期最终执行。

2.Func<>谓词表达式,就是一个委托,委托一旦调用,就立即执行了,将执行结果保存在内存中。

那么在EF中我们根据条件查询数据时,不应该把数据一次性加载到本地内存中,然后再本地内存中进行筛选,如果数据量大了,就崩溃了。

我们需要将表达式组合好,然后再一起提交到数据库执行,返回查询结果。(那这句话的意思是在ef查询中用Iqueryable接收)

每次在执行where查询操作符的时候IQueryProvider会为我们创建一个新的IQueryable<T>,调用AsEnumerable()方法的时候并不会去实际取值,只是

得到了一个IEnumerable,所以EF在查询数据时候不要先取IEnumerable再去筛选数据。执行ToList方法时才会去真正调用迭代器GetEnumerator()
取值。真正取值时候,会去执行IQueryProvider中的Excute方法.(解析表达式,然后执行取得结果))

这就是IQueryable的延迟加载把.


  

IEnumerable<T>和IQueryable<T>区分

标签:csdn   arp   为我   http   tar   运行   object   数据库   排序   

原文地址:https://www.cnblogs.com/ZkbFighting/p/9142646.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!