Loading all results into memory first is wasteful. IAsyncEnumerable streams results as they’re retrieved.
Old Way – Load Everything:
public async Task> GetOrdersAsync() { return await _db.Orders.ToListAsync(); // Loads all 1 million orders into memory! } // Caller: var orders = await GetOrdersAsync(); // 5GB in memory foreach (var order in orders) ProcessOrder(order);
Stream with IAsyncEnumerable:
public async IAsyncEnumerableGetOrdersAsync() { await foreach (var order in _db.Orders.AsAsyncEnumerable()) { yield return order; } } // Caller: await foreach (var order in GetOrdersAsync()) { ProcessOrder(order); // Processes one at a time, low memory! }
Benefits:
– Low memory usage
– Start processing immediately
– Can cancel mid-stream
