C#中IQueryable和IEnumerable的區別


最近的一個面試中,被問到IQueryable 和 IEnumerable的區別, 我自己看了一些文章,總結如下:

1. 要明白一點,IQueryable接口是繼承自IEnumerable的接口的.

2. IQueryable中有表達式樹, 這可以看作是它的一個優勢。所以,使用IQueryable操作時,比如對數據的過濾,排序等操作, 這些都會先緩存到表達式樹中. 當對數據庫操作真正發生時,它才會將表達式樹執行來獲取數據。

   這也就是說,比如選擇top 2兩行數據, 它會先在表達式樹中緩存這個過濾取top 2的操作。待到操作數據庫時,它就會在數據庫中篩選top 2數據。 =》 IQueryable 有延時加載機制, 它直接從數據庫中篩選數據.

3. IEnumerable, 它對數據進行操作時,和IQueryable不同,它會事先把所有的數據從數據庫獲取,放到內存中。然后,在內存中對這些數據進行篩選操作,包括過濾,排序等.  => IEnumerable 在內存中對數據進行篩選

 

我們通過舉一個用Repository的例子來說明

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中調用

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]

可見,它只從數據庫中取出了兩條數據

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM