π C# Tip β IEnumerable vs IQueryable (The Difference That Actually Matters)
IEnumerable and IQueryable look similar.
Theyβre not.
Choosing the wrong one can lead to:
- Performance issues
- Loading way too much data
- Queries that work in dev and explode in prod
Letβs clarify this once and for all.
π§ The Core Difference
IEnumerable<T>β In-memory iterationIQueryable<T>β Query definition (deferred, remote execution)
That distinction drives everything else.
π§© IEnumerable β In-Memory Execution
IEnumerable<Order> orders = GetOrders(); var expensive = orders .Where(o => o.Total > 100) .ToList();
What really happens:
- Data is already in memory
- LINQ runs inside your process
- Filtering happens after data is loaded
β
When to use IEnumerable
- Collections already in memory
- Small datasets
- Business logic
- APIs returning final results
β οΈ Risks
- Accidental full-table loads
- Hidden performance costs
- Late discovery of inefficiencies
π§© IQueryable β Query Translation
IQueryable<Order> orders = context.Orders; var expensive = orders .Where(o => o.Total > 100) .ToList();
What really happens:
- LINQ builds an expression tree
- Provider (EF Core, LINQ-to-SQL) translates it
- Filtering runs in the database
β
When to use IQueryable
- Data access layer
- EF Core queries
- OData / dynamic filtering
- Server-side paging, sorting, projection
β οΈ Risks
- Leaking
IQueryableoutside repositories - Runtime query translation errors
- Hidden N+1 queries
- Security & performance surprises
βοΈ Side-by-Side Comparison
| Aspect | IEnumerable | IQueryable |
|---|---|---|
| Execution | In memory | Remote (DB, provider) |
| LINQ runs | In .NET | Translated to SQL |
| Performance | Depends on size | Depends on query |
| Deferred execution | β | β |
| Safe to expose | β | β οΈ |
| Best layer | Domain / App | Data access |
π§ The Most Common Mistake
β Returning IQueryable from repositories:
public IQueryable<Order> GetOrders() { return _context.Orders; }
Why this is dangerous:
- Leaks persistence concerns
- Couples callers to EF Core
- Makes performance unpredictable
β Better:
public Task<List<Order>> GetOrdersAsync() { return _context.Orders .Where(o => o.IsActive) .ToListAsync(); }
ποΈ A Clean Rule of Thumb
- Use
IQueryableto build queries - Use
IEnumerableto consume data
Or even simpler:
IQueryablebelongs to the infrastructure layer
IEnumerablebelongs everywhere else
β οΈ Extra Gotchas (Real-World)
- Calling
.AsEnumerable()switches execution to memory - Mixing
IQueryable+ custom C# methods breaks translation IQueryableerrors show up at runtime, not compile time- Logging SQL is essential when using
IQueryable
π― Final Takeaway
IQueryable is powerful β and dangerous.
IEnumerable is safe β and sometimes expensive.
Choosing between them is not a syntax choice.
Itβs a data flow and responsibility choice.
Most performance bugs start with
βIt was just anIQueryableβ¦β
#dotnet #csharp #linq #efcore #performance #softwarearchitecture #cleancode
