No one has actually explained the difference between ToListAsync()
and AsAsyncEnumerable()
.
ToListAsync()
will fetch all of the results of the query into memory, and then return the collection of results as a single List<T>
object. It will do this asynchronously, so that it doesn't block on I/O, but it won't return anything until all of the results are available.
AsAsyncEnumerable()
will "yield" each result as it's available. In the OP's example, they're simply calling ToList()
, so the result is the same. However, since C# 8.0 you could also use an "async stream" such as await foreach
, and then act on each entity as it's returned. For example:
await foreach (var entity in DbContext.Set<Record>.Where(predicate).AsAsyncEnumerable())
{
// do something with entity...
}
As to which is "better", it depends on your use-case. If you're just returning a few records to the caller, ToListAsync()
should be fine.
However, suppose your query will return 10,000 records. You probably don't want to store all those in memory before you act on them, because the query might run for many seconds or even minutes and will use lots of memory.
In that case, it's probably better to use an async stream. This could be your own async IAsyncEnumerable<T>
method which yield
s its own results. You can then chain these together if needed.
In fact, since ASP.NET Core 6, you can return an IAsyncEnumerable<T>
directly from your controller method, and it will "stream" those results back to the caller.
This makes it much more efficient to write code which operates on and/or returns a large number of records, because there's never a point where they're buffered into memory.