Facilitating the Spread of Knowledge and Innovation in Professional Software Development

Write for InfoQ


Choose your language

InfoQ Homepage News Async Streaming with EF Core and ASP.NET Core 6

Async Streaming with EF Core and ASP.NET Core 6

This item in japanese

A long running problem in ASP.NET has been the inability to handle returning large JSON files without consuming a lot of memory. The default behavior for the framework is to buffer the entire output at once, convert it en masse to JSON, and then start feeding the results to the client. This can lead to out-of-memory situations if the amount of data is large enough.

The inability to stream results was never a fundamental problem for ASP.NET. When working with simpler formats such as CSV, the developer has always had the ability write directly to the result stream.

Starting with ASP.NET Core 5, the Utf8JsonWriter class can be used for the same effect. The code has a few complexities to it, such as the need to explicitly disable buffering, but can work if you follow the instructions provided by Alexander Vasilyev.

ASP.NET Core 6 makes this easier by directly supporting IAsyncEnumerable. If an IAsyncEnumerable is returned by a function, the framework will interpret it as a request to stream the data to the client asynchronously without buffering.

One way to get an IAsyncEnumerable is to use Entity Framework Core. This has actually been a feature since EF Core 3, but its utility in web servers has been limited until now. ASP.NET Core didn’t support IAsyncEnumerable results until version 5, and even then it would still buffer the results.

In ASP.NET Core Announcements #463, developers were informed that the new IAsyncEnumerable should be considered a breaking change.

In most cases, the absence of buffering would not be observed by the application. However, some scenarios may have inadvertently relied on the buffering semantics to correctly serialize. For instance, returning an IAsyncEnumerable<> that is backed by a EF query on a type with lazy loaded properties might result in concurrent query execution which might be unsupported by the provider.

In order to revert back to the previous behavior, developers need to explicitly call ToListAsync(). Alternately, they can disable behaviors such as lazy loading.

Rate this Article