.NETMedium
IQueryable vs IEnumerable in EF Core — what is the practical difference?
IQueryable<T> builds an expression tree that EF translates to SQL. Filters compose on the database side.
IQueryable<Product> q = db.Products;
q = q.Where(p => p.IsActive); // not executed yet
q = q.Where(p => p.Price < 100m); // composed into the same SQL
var rows = await q.ToListAsync(); // ONE SQL query: WHERE IsActive AND Price < 100
IEnumerable<T> materialises in memory; further LINQ runs client-side.
IEnumerable<Product> q = db.Products.ToList(); // SELECT * FROM Products
q = q.Where(p => p.IsActive); // filtered in-process
q = q.Where(p => p.Price < 100m); // also in-process
The IEnumerable version pulls every row into memory, then filters. On a table with 1M rows that's millions of bytes loaded across the network for no reason.
Gotcha: calling AsEnumerable() mid-chain ends the query translation:
var rows = await db.Products
.Where(p => p.IsActive)
.AsEnumerable() // ⚠ everything after this is in-memory
.Where(p => p.Name.StartsWith("A")) // filtered AFTER fetching all active rows
.ToListAsync();
Rule: keep filters on IQueryable for as long as possible. The compiler doesn't warn you when you cross the line.