在使用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