🔍 Deferred Execution
IEnumerable vs IQueryable — quais métodos executam SQL e por quê
Regra prática: qualquer método "materializador" (ToList, Any, Count, foreach...) dispara o SQL. Tudo antes é apenas a definição da query — nada vai pro banco.
| Aspecto | IEnumerable<T> | IQueryable<T> |
|---|---|---|
| Onde filtra | Memória (C#) | Banco (SQL WHERE) |
| Carrega tudo? | Sim — todos os registros | Não — só o necessário |
| LINQ provider | LINQ to Objects | LINQ to SQL (EF Core) |
| AsEnumerable() | Muda o contexto — tudo depois roda em memória, não em SQL | |
// ❌ RUIM: carrega TUDO em memória, filtra no C#
var bad = await db.Orders.ToListAsync(); // SELECT * FROM Orders (sem WHERE)
var filtered = bad.Where(o => o.Total > 100); // filtra em C# — pode ser 1M registros
// ✅ BOM: filtra no banco via SQL
var good = await db.Orders
.Where(o => o.Total > 100) // WHERE Total > 100
.ToListAsync(); // executa o SQL
// ⚠️ AsEnumerable() muda o contexto para memória
var mixed = db.Orders
.Where(o => o.Status == "Open") // → SQL WHERE
.AsEnumerable() // ← switch para memória
.Where(o => o.Note.Contains("x"));// → C# (não SQL)
// ⚠️ foreach também materializa
foreach (var o in db.Orders.Where(o => o.Total > 100)) // SQL executa AQUI
Console.WriteLine(o.Id);