Entity Framework返回IEnumerable还是IQueryable?
在使用EF的过程中,我们常常使用repository模式,本文就在repository层的返回值是IEnumerable类型还是IQueryable进行探讨。
阅读目录:
一、什么是Repository模式?
二、IEnumerable还是IQueryable的区别
三、实际检验IEnumerable和IQueryable的效率差别
四、总结
一, 什么是Repository模式?
Repository是隔离在数据访问层和业务逻辑层之间的。它提供业务逻辑各种对象,使得业务逻辑代码不需要关心数据是如何存储和获取的。
下图,是MVC中使用Repository模式的模型图。Controller调用Repository来获取数据,而Repository调用EF来访问数据库。
Repository模式的好处是它为逻辑和数据访问解耦,使得它们之间没有互相依赖。Repository可以挑选不同的数据来源,不如MySql, WCF, Web Service等,都不会影响到业务逻辑的改动。

一段典型的Repository代码类似于:
public class DailyReportRepository : IDailyReportRepository
{
private readonly Context _context; public DailyReportRepository(Context context)
{
_context = context;
} public IQueryable<dailyreport> GetAllDailyReports()
{
return from report in _context.dailyreports
select report;
} public IEnumerable<dailyreport> GetAllDailyReports(DateTime start, DateTime end)
{
var query = from report in GetAllDailyReports()
where
report.EntryDate >= start && report.EntryDate < end
select report; return query;
}
}
二,IEnumerable还是IQueryable的区别
上面的代码中,函数的返回值一个是IEnumerable类型,一个是IQuerable类型,它们有什么不同呢? 那个更好?
IQueryable继承自IEnumerable,所以对于数据遍历来说,它们没有区别。
但是IQueryable的优势是它有表达式树,所有对于IQueryable的过滤,排序等操作,都会先缓存到表达式树中,只有当真正遍历发生的时候,才会将表达式树由IQueryProvider执行获取数据操作。
而使用IEnumerable,所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说数据已经从数据库中获取到了内存中,只是在内存中进行过滤和排序操作。
三,实际检验IEnumerable和IQueryable的效率差别
Repository的代码如下, 返回同样的数据,一个使用IEnumerable,一个使用IQueryable
public class StudentRepository : IStudentRepository
{
private readonly SchoolContext _context; public StudentRepository(SchoolContext context)
{
_context = context;
} public IEnumerable<Student> GetIEnumerableStudents()
{
return _context.Students;
} public IQueryable<Student> GetIQueryableStudents()
{
return _context.Students;
}
}
在Controller中分别调用, 从Repository中返回的数据中,取2条显示在页面上。
public class HomeController : Controller
{
private readonly IStudentRepository _studentRepository;
public HomeController(IStudentRepository studentRepository)
{
_studentRepository = studentRepository;
} public ActionResult Index()
{
//Repository使用IEnumerable返回结果
var students = _studentRepository.GetIEnumerableStudents().Take();
//Repository使用IQueryable返回结果
//var students = _studentRepository.GetIQueryableStudents().Take(2);
return View(students);
}
}
呈现的页面如下:

但是通过MiniProfiler检测到的结果,使得真相水落石出。
前面一张是使用IEnumerable返回值的,后面一张是使用IQueryable返回值。
对比能够发现,使用IQueryable的查询,Take(2)的操作是通过Sql在数据库中完成的。
试想在数据较多的情况下或者操作比较复杂的情况下,IEnumerable的效率会比IQueryable低很多。


四,总结
结论应当非常明显,使用IQueryable作为Repository的返回值是我们最终的选择。
同时对于IQueryable有兴趣,不妨多深入研究。里面涉及的表达式树,是.net中的非常重要的概念。
下篇讨论,如何使用表达式树来增加Repository代码的灵活性。
Entity Framework返回IEnumerable还是IQueryable?的更多相关文章
- 使用 Entity Framework 返回 JsonResult 时循环引用的避免【EF 转 JSON】
var ui = (from u in _db.USER_INFO select u).FirstOrDefault(); // 单个实体的用法 ZRQCommon.EntitiesTools e = ...
- 分享基于Entity Framework的Repository模式设计(附源码)
关于Repository模式,在这篇文章中有介绍,Entity Framework返回IEnumerable还是IQueryable? 这篇文章介绍的是使用Entity Framework实现的Rep ...
- Entity Framework后台采用分页方式取数据与AspNetPager控件的使用
本文是一个对AspNetPager控件使用的笔记! 有关AspNetPager控件可以查看杨涛主页.这是一个开放的自定义ASP.NET控件,支持各种自定义的数据分页方式,使用很方便,而且功能也很强大, ...
- Entity Framework中IQueryable, IEnumerable, IList的区别(转载)
原文:http://www.cnblogs.com/hiteddy/archive/2011/10/01/Difference_among_IQueryable_IEnumeralb_IList_in ...
- Entity Framework中IQueryable, IEnumerable, IList的区别[转]
使用工具追踪EF生成的SQL 使用Entity Framework等ORM框架的时候,SQL对于使用者来说是透明的,往往很多人也不关心ORM所生成的SQL,然而系统出现性能问题的时候就必须关注生成的S ...
- Entity Framework Core今日所得:避免 IEnumerable 以及 IQueryable 陷阱
避免 IEnumerable 以及 IQueryable 陷阱: IEnumerable示用Linq会先去数据库查询所有记录,然后再条件查询. IQueryable接口派生自IEnumerable,但 ...
- Entity Framework快速入门--IQueryable与IEnumberable的区别
IEnumerable接口 公开枚举器,该枚举器支持在指定类型的集合上进行简单迭代.也就是说:实现了此接口的object,就可以直接使用foreach遍历此object: IQueryable 接口 ...
- Entity Framework DbSet<T>之Include方法与IQueryable<T>扩展方法Include的使用
Entity Framework使用Code First方式时,实体之间已经配置好关系,根据实际情况某些情况下需要同时获取导航属性,比如获取商品的同时需要获取分类属性(导航属性),或者基于优化方面考虑 ...
- 《Entity Framework 6 Recipes》中文翻译系列 (14) -----第三章 查询之查询中设置默认值和存储过程返回多结果集
翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 3-6在查询中设置默认值 问题 你有这样一个用例,当查询返回null值时,给相应属性 ...
随机推荐
- 20151208Study
20151208-----------------------------------------------------* Her main interest now is raising her ...
- vps云服务器建站后绑定域名的方法?
有很多的新手站长们,都不知道vps建站后该如何绑定自己的域名,这里就Windows系统的VPS主机利用iis绑定网站域名的方法,简要介绍一下. 通常情况下,我们在使用IIS建站的时候,都会有一步提示, ...
- Android安全之Intent Scheme Url攻击
0X01 前言 Intent scheme url是一种用于在web页面中启动终端app activity的特殊URL,在针对intent scheme URL攻击大爆发之前,很多android的浏览 ...
- C# 动态加载程序集dll (实现接口)
一.程序集(接口程序集):LyhInterface.Dll namespace LyhInterface { public interface ILyhInterface { void Run(); ...
- LinuxMM--Memory Pressure
Memory pressure定义在操作系统中,用户分配.文件缓存.网卡包缓冲区等等都会消耗内存.一旦出现内存紧张就会导致memory pressure.引发当某个任务需要请求内存时就有可能引发mem ...
- ZOJ3791_An Easy Game
给出两个等长的字符串,每次需要改变m个数字,每次必须改变k个数字,求从第一个串变化到第二个串的方案数. DP.f[i][j]改变i步后,有j个位置被改变的方案数.然后直接枚举当前改变的几个位置是前面重 ...
- awk 的一些用法
awk,我觉得是Linux里面处理文本最精妙的命令,它是一个行处理的命令,它最初级的用法是:给定一些简单的pattern,然后按照这个pattern 去搜索匹配的行.它的高级用法是用awk来编程,除了 ...
- The Singleton pattern
作为对象的创建模式,单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的结构 单例模式的特点: 单例类只能有一个实例. 单例类必须自己创建自己的唯一 ...
- Tomcat服务器8080端口占用报错
报错信息如下: Oct , :: PM org.apache.coyote.AbstractProtocol init SEVERE: Failed to initialize end point a ...
- hadoop多次搭建后,完整总结(累死宝宝了,搭建了十多遍了)
1.安装JDK1.1上传运用软件FileZilla,将windows上的jdk压缩包放到linux的root目录下 1.2解压jdk #创建文件夹 mkdir /usr/java(不要挂在在" ...