EF 中 IEnumberable<> 和 IQueryable的区别

首先一点: IQueryable interface 继承自 IEnumberable interface , 所以 IEnumberable 能做的 IQueryable 都能做;

共同点: 

  1、两者都是延迟加载(Lazy Loading) , 

  2、EF 使用中共同的方法: where() , skip() ,  OrderbyDescending() , Take() etc ,

    以上这些方法都有两个版本:

      IEnumberable 版本:   Where(Func<Customer, bool> predicate)      

      IQueryable 版本:  Where(Expression<Func<Customer, bool>> predicate) 

                 其中 Expression对象的Compile() 执行后  为 Func<>类型

  3、. AsEnumerable() 方法 使用IEnumberalbe接口, .AsQueryable() 使用IQueryable接口 

不同点:

  1、IQueryable 允许 LINQ-to-SQL ,  转化成的sql 语句在服务器端执行 

      2、IEnumberable 允许 LINQ-to-Object, 不允许转化成SQL,   只能操作内存中的数据;

下面通过代码说明:

1、使用EF中IEnumberable 接口的方法 where()  执行过滤 Empid=2的 Employess 

EmpEntities ent = new EmpEntities();
IEnumerable<Employee> emp = ent.Employees; 
IEnumerable<Employee> temp = emp.Where(x => x.Empid == 2).ToList<Employee>();

这个操作 生成的SQL语句是: 

SELECT * FROM [dbo].[ Employees]          /// 获取所有的 Employees

执行过程是: 从数据库中获取所有的 Employees 到客户端(内存)中, 在内存中执行过滤操作(where()方法)。  

执行过程如下图示:

从上可以看出: 这种 查询 方法时比较慢, 因为查询出了所有的数据;

2、 使用EF 中 IQueryable interface的方法 .where() 执行相同的操作;

EmpEntities ent = new EmpEntities();
IQueryable<Employee> emp = ent.Employees;
IQueryable<Employee> temp =  emp.Where(x => x.Empid == 2).ToList<Employee>();

生成的SQL语句使: 

SELECT TOP 1 * FROM [dbo].[ Employees] WHERE [Empid] =10 

执行过程如下图所示:

这种执行方式, 通过成的SQL语句 , 在服务器端 执行过滤操作, 然后将符合条件的数据返回客户端(内存中), 而不是将所有的数据都返回到客户端, 

总结:

过滤内存中的数据 IEnumberable 接口的方法随时可以使用;

查询数据库IQueryable 接口的方法,是一个比较好的选择,但是IQueryable接口方法中 使用LINQ语句, 会有一些语句不识别, 比如 自定义方法, 识别都是能够转化成sql语句的方法;

使用EF , 效率问题是必须要注意的问题,尤其是查询数据,很容造成 n+1问题 、 返回所有数据问题 , 造成查询效率低下;

PS:  上面图示部分来自 参考资料

What is the difference between IQueryable<T> and IEnumerable<T>?

Returning IEnumerable<T> vs. IQueryable<T>

英文版的 技术资料 真的很齐全, 做技术方面还是要多读英文资料;

原文地址:https://www.cnblogs.com/generalLi/p/6909216.html