What is the difference between IQueryable and IEnumerable?
See also What\'s the difference between IQueryable and I
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:
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:
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.