在使用EF的过程当中,咱们经常使用repository模式,本文就在repository层的返回值是IEnumerable类型仍是IQueryable进行探讨。html
阅读目录:数据库
1、什么是Repository模式?缓存
2、IEnumerable仍是IQueryable的区别ide
3、实际检验IEnumerable和IQueryable的效率差异函数
4、总结url
Repository是隔离在数据访问层和业务逻辑层之间的。它提供业务逻辑各类对象,使得业务逻辑代码不须要关心数据是如何存储和获取的。spa
下图,是MVC中使用Repository模式的模型图。Controller调用Repository来获取数据,而Repository调用EF来访问数据库。.net
Repository模式的好处是它为逻辑和数据访问解耦,使得它们之间没有互相依赖。Repository能够挑选不一样的数据来源,不如MySql, WCF, Web Service等,都不会影响到业务逻辑的改动。3d
一段典型的Repository代码相似于:code
publicclass DailyReportRepository : IDailyReportRepository{ privatereadonly Context _context; public DailyReportRepository(Context context) { _context = context; } public IQueryable<dailyreport> GetAllDailyReports() { returnfrom 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类型,一个是IQuerable类型,它们有什么不一样呢? 那个更好?
IQueryable继承自IEnumerable,因此对于数据遍从来说,它们没有区别。
可是IQueryable的优点是它有表达式树,全部对于IQueryable的过滤,排序等操做,都会先缓存到表达式树中,只有当真正遍历发生的时候,才会将表达式树由IQueryProvider执行获取数据操做。
而使用IEnumerable,全部对于IEnumerable的过滤,排序等操做,都是在内存中发生的。也就是说数据已经从数据库中获取到了内存中,只是在内存中进行过滤和排序操做。
Repository的代码以下, 返回一样的数据,一个使用IEnumerable,一个使用IQueryable
publicclass StudentRepository : IStudentRepository{ privatereadonly 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条显示在页面上。
publicclass HomeController : Controller{ privatereadonly IStudentRepository _studentRepository; public HomeController(IStudentRepository studentRepository) { _studentRepository = studentRepository; } public ActionResult Index() { //Repository使用IEnumerable返回结果var students = _studentRepository.GetIEnumerableStudents().Take(2); //Repository使用IQueryable返回结果 //var students = _studentRepository.GetIQueryableStudents().Take(2);return View(students); }}
呈现的页面以下:
可是经过MiniProfiler检测到的结果,使得真相水落石出。
前面一张是使用IEnumerable返回值的,后面一张是使用IQueryable返回值。
对比可以发现,使用IQueryable的查询,Take(2)的操做是经过Sql在数据库中完成的。
试想在数据较多的状况下或者操做比较复杂的状况下,IEnumerable的效率会比IQueryable低不少。
结论应当很是明显,使用IQueryable做为Repository的返回值是咱们最终的选择。
同时对于IQueryable有兴趣,不妨多深刻研究。里面涉及的表达式树,是.net中的很是重要的概念。
转载:http://www.cnblogs.com/JustRun1983/archive/2013/08/15/3261074.html