最近的一個面試中,被問到IQueryable 和 IEnumerable的區別, 我本身看了一些文章,總結以下:面試
1. 要明白一點,IQueryable接口是繼承自IEnumerable的接口的.數據庫
2. IQueryable中有表達式樹, 這能夠看做是它的一個優點。因此,使用IQueryable操做時,好比對數據的過濾,排序等操做, 這些都會先緩存到表達式樹中. 當對數據庫操做真正發生時,它纔會將表達式樹執行來獲取數據。緩存
這也就是說,好比選擇top 2兩行數據, 它會先在表達式樹中緩存這個過濾取top 2的操做。待到操做數據庫時,它就會在數據庫中篩選top 2數據。 =》 IQueryable 有延時加載機制, 它直接從數據庫中篩選數據.測試
3. IEnumerable, 它對數據進行操做時,和IQueryable不一樣,它會事先把全部的數據從數據庫獲取,放到內存中。而後,在內存中對這些數據進行篩選操做,包括過濾,排序等. => IEnumerable 在內存中對數據進行篩選spa
咱們經過舉一個用Repository的例子來講明code
public class EmployeeRepository : IEmployeeRepository { private readonly CompanyContext _context; public EmployeeRepository(CompanyContext context) { _context = context; } public IEnumerable<Employee> GetIEnumerableEmployees() { return _context.Employees; } public IQueryable<Employee> GetIQueryableEmployees() { return _context.Employees; } }
在Controller中調用blog
public class HomeController : Controller { private readonly IEmployeeRepository _employeeRepository; public HomeController(IEmployeeRepository employeeRepository) { _employeeRepository = employeeRepository; } public ActionResult Index() { //用IEnumerable返回結果測試 var employees = _employeeRepository.GetIEnumerableEmployees().Take(2); //用IQueryable返回結果測試 // var employees = _employeeRepository.GetIQueryableEmployees().Take(2); return View(employees); } }
使用MiniProfiler來檢測,會發現二者的區別排序
使用IEnumerable檢測發現,它在數據庫中執行的語句是:繼承
SELECT [Extent].[Id] AS [Id], [Extent].[Name] AS [Name], [Extent].[Department] AS [Department] FROM [dbo].[Employee] AS [Extent]
可見,它從數據庫中取出了全部數據。而後在內存中再篩選.接口
使用IQueryable檢測發現,它在數據庫中執行的語句是:
SELECT TOP (2) [Extent].[Id] AS [Id], [Extent].[Name] AS [Name], [Extent].[Department] AS [Department] FROM [dbo].[Employee] AS [Extent]
可見,它只從數據庫中取出了兩條數據