{
  "id": 10506227,
  "title": "Async LINQ: Why ToListAsync Exists (And Why WhereAsync Doesn't)",
  "url": "https://urgent.news/2026/09/28/async-linq-why-tolistasync-exists-and-why-whereasync-doesnt",
  "topic": "tech",
  "section": "Tech",
  "published": "2026-09-28T18:34:00.000Z",
  "source": {
    "name": "Dev.to",
    "slug": "dev-to",
    "url": "https://dev.to/homolibere/async-linq-why-tolistasync-exists-and-why-whereasync-doesnt-2imk"
  },
  "original_language": "en",
  "account": "In LINQ, operators like Where, Select, and OrderBy do not execute any operations. They create a query - an expression tree - that gets executed at a terminal operator such as ToList, First, Count, or Any. This is when data is transferred over the network. It's at this point that one would typically use an async method, hence the existence of ToListAsync. However, there is no WhereAsync because the Where operator does not interact with the database. If it had an async version, it would not add any value.\n\nEntity Framework Core provides async versions of all operators that trigger execution, including ToListAsync, ToArrayAsync, ToDictionaryAsync, CountAsync, SumAsync, AverageAsync, MaxAsync, FirstAsync, FirstOrDefaultAsync, SingleAsync, SingleOrDefaultAsync, AnyAsync, AnyAsync, AllAsync, FindAsync, and others. Each one triggers actual database communication and should be awaited.\n\nAdditionally, there's a streaming async pattern - ToListAsync waits for all rows before returning, which could be inefficient for large result sets. The AsAsyncEnumerable() method can be used instead, which asynchronously fetches items one at a time, preventing the entire result set from being held in memory.\n\nIn async code, ConfigureAwait(false) is often used to avoid capturing the synchronization context, preventing deadlocks and improving performance in application code. But for library code, this should always be added. Mixing sync and async calls can also be problematic. For example, awaiting OnCompleted() in an async method blocks the thread. Similarly, using Task.Run() with async operations is not ideal as it does not release the thread during I/O operations.\n\nAnother common pitfall is the false async, where Task.Run is used to execute a query and await it. This does not make the query async; it merely runs it on a different thread. Parallel execution of DbContext operations is also a mistake because DbContext is not thread-safe. Instead, separate DbContext instances should be used for parallel operations.",
  "summary": "Async LINQ: Why ToListAsync Exists (And Why WhereAsync Doesn't) You write await dbContext.Products.ToListAsync() . Good. Then you wonder: where's WhereAsync ? Why isn't await dbContext.Products.WhereAsync(p => p.Price > 100) ? The answer reveals something fundamental about how LINQ actually works. Where the Async Boundary Lives LINQ operators like Where , Select , OrderBy don't execute anything.…",
  "key_points": [
    "ToListAsync exists to execute LINQ queries asynchronously at terminal operators.",
    "WhereAsync doesn't exist because Where operator doesn't interact with the database.",
    "Entity Framework Core provides async versions of execution-triggering operators."
  ],
  "editors_take": null,
  "illustration": null,
  "coverage": {
    "outlets": 1,
    "also_reported_by": []
  },
  "ai_generated": true,
  "disclaimer": "Summaries, key points and the editor’s take are written by software from other outlets’ reporting and may contain errors — always check the linked original."
}