Introduction
If you are learning C#, LINQ, or Entity Framework Core, you will often see two interfaces:
IEnumerable<T>
IQueryable<T>
Both are used with LINQ, but they work differently.
The main difference is where the query runs.
What is IEnumerable in C#?
IEnumerable<T> is mainly used when the data is already available in memory.
For example :
List<int> numbers = new()
{
10, 20, 30, 40, 50
};
IEnumerable<int> result = numbers
.Where(x => x > 20);
Here, the numbers are already in memory, so the Where() condition runs inside the application.
Simple flow :
Data → Memory → LINQ → Result
IEnumerable is commonly used with:
List<T>
Arrays
Collections
In-memory data
What is IQueryable in C#?
IQueryable<T> is mainly used for querying external data sources, especially databases.
For example, with Entity Framework Core:
IQueryable<Product> products = dbContext.Products;
var result = await products
.Where(x => x.Price > 1000)
.ToListAsync();
Entity Framework Core can convert this LINQ query into SQL.
It may generate SQL similar to:
SELECT * FROM Products WHERE Price > 1000;
The filtering happens in the database instead of loading all products into memory.
Simple flow :
LINQ Query → SQL → Database → Result
IEnumerable vs IQueryable
| Feature | IEnumerable | IQueryable |
|---|
| Works mainly with | In-memory data | Database data |
| Query runs | In application | Usually at database |
| SQL translation | No | Yes, through provider |
| Best for | Small/in-memory collections | Database queries |
| Common with | List, Array | Entity Framework Core |
A Database Example
Suppose we have a Products table containing 1 million records.
We want products where:
Price > 1000
Using IQueryable
With Entity Framework Core:
IQueryable<Product> products = dbContext.Products;
var result = await products
.Where(x => x.Price > 1000)
.ToListAsync()
Conceptually, the process is:
Application
↓
LINQ Where(x => x.Price > 1000)
↓
Entity Framework Core
↓
SQL
↓
Database
↓
Only matching records
↓
Application
The filtering is performed by the database.
What Happens When You Switch to IEnumerable?
IQueryable<Product> products = dbContext.Products;
IEnumerable<Product> result = products
.AsEnumerable()
.Where(x => x.Price > 1000);
AsEnumerable() changes the LINQ operations that follow it to LINQ-to-Objects.
So the Where() after AsEnumerable() is evaluated in the application.
Conceptually:
Database
↓
Records are read
↓
Application memory
↓
Where(x => x.Price > 1000)
↓
Filtered result
This can be slow if the database has a lot of records.
If the database contains a large number of records, this can result in unnecessary data transfer and increased memory usage.
Conclusion
IEnumerable<T> is mainly used for working with data in application memory, while IQueryable<T> is used to build queries that can be executed by external data sources such as databases. Understanding where the query is executed helps you write more efficient and performant LINQ and Entity Framework Core code.
Hope this helps you!