What is the difference between IQueryable and IEnumerable?

前端 未结 12 1905
梦毁少年i
梦毁少年i 2020-11-22 06:41

What is the difference between IQueryable and IEnumerable?


See also What\'s the difference between IQueryable and I

12条回答
  •  离开以前
    2020-11-22 06:50

    Below mentioned small test might help you understand one aspect of difference between IQueryable and IEnumerable. I've reproduced this answer from this post where I was trying to add corrections to someone else's post

    I created following structure in DB (DDL script):

    CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
    

    Here is the record insertion script (DML script):

    INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
    INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
    INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
    INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
    INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
    GO
    

    Now, my goal was to simply get top 2 records from Employee table in database. I added an ADO.NET Entity Data Model item into my console application pointing to Employee table in my database and started writing LINQ queries.

    Code for IQueryable route:

    using (var efContext = new EfTestEntities())
    {
        IQueryable employees = from e in efContext.Employees  select e.Salary;
        employees = employees.Take(2);
    
        foreach (var item in employees)
        {
            Console.WriteLine(item);
        }
    }
    

    When I started to run this program, I had also started a session of SQL Query profiler on my SQL Server instance and here is the summary of execution:

    1. Total number of queries fired: 1
    2. Query text: SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]

    It is just that IQueryable is smart enough to apply the Top (2) clause on database server side itself so it brings only 2 out of 5 records over the wire. Any further in-memory filtering is not required at all on client computer side.

    Code for IEnumerable route:

    using (var efContext = new EfTestEntities())
    {
        IEnumerable employees = from e in efContext.Employees  select e.Salary;
        employees = employees.Take(2);
    
        foreach (var item in employees)
        {
            Console.WriteLine(item);
        }
    }
    

    Summary of execution in this case:

    1. Total number of queries fired: 1
    2. Query text captured in SQL profiler: SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]

    Now the thing is IEnumerable brought all the 5 records present in Salary table and then performed an in-memory filtering on the client computer to get top 2 records. So more data (3 additional records in this case) got transferred over the wire unnecessarily.

提交回复
热议问题