DEV Community

Janki Mehta
Janki Mehta

Posted on

Optimizing EF Core Performance with Async Querying in .NET 6

Entity Framework Core (EF Core) is the go-to ORM for .NET developers. It provides an abstraction over your database, allowing you to query and persist objects without writing SQL. However, there are some best practices around async querying that can greatly improve EF Core performance.

In this post, we'll explore some key methods to optimize async database access in EF Core within .NET 6 applications.

Why Async Queries?

Performing synchronous blocking queries can significantly degrade the performance of your API or application, especially under load. Blocking calls prevent your thread from doing any other work.
By making queries asynchronous, you enable the thread to be freed up while waiting for the result from the database. This allows your app to handle more concurrent requests and improves scalability.

Async Query Methods

The main methods we want to make asynchronous are database read operations like:

  • ToListAsync
  • FirstOrDefaultAsync
  • SingleOrDefaultAsync
  • CountAsync

Here is an example synchronous query:

// Blocking synchronous query
var customers = context.Customers.ToList();
Enter fullscreen mode Exit fullscreen mode

And the async equivalent:

// Asynchronous query 
var customers = await context.Customers.ToListAsync();

Enter fullscreen mode Exit fullscreen mode

The key differences are:

  • Adding the async keyword to the method
  • Using await when calling the async method
  • Changing the method name by appending Async
  • This allows executing the query in a non-blocking manner.

Configure Async Queries

In EF Core 6, asynchronous query behavior must be explicitly opted into for DbContext types. This involves:

  • Marking DbContext derived types with [AsyncQuery] attribute
  • Making async query methods virtual

For example:

[AsyncQuery]
public class MyContext : DbContext 
{
  public virtual IQueryable<Customer> Customers => Set<Customer>();

  // Other DbSet properties
}
Enter fullscreen mode Exit fullscreen mode

This enables your DbContext to leverage asynchronous query methods.

Performance Benefits

  • Converting synchronous queries to async can provide significant speed improvements:
  • More concurrent requests - Less blocking allows handling more simultaneous requests
  • Scalability - Your app can scale better across additional compute resources
  • Faster responses - Eliminates extra context switching and waiting

The exact benefits will depend on your infrastructure, queries, and traffic. But generally, async EF Core queries can handle 2-3x more concurrent users versus blocking queries before becoming CPU bound.

Handling Async Code

You'll need to propagate it up the call stack when going async. Key points:

  • Controller actions should be marked async and use await
  • Avoid blocking calls like .Result or .Wait() as this eliminates the benefits
  • Configure IHost and dependency injection for async (services scoped)

With some adjustments to code flow, your app can fully leverage non-blocking EF Core queries for maximum efficiency.

While optimizing ORM performance is important, these types of in-depth .NET optimizations are best handled by an experienced developer. Hire .NET developers who understands async programming, EF Core internals, and performance profiling will ensure you properly implement async querying. They can also advise on other application bottlenecks. Finding a .NET developer skilled in writing high-performance C# code will enable you to build robust, production-ready apps.

Top comments (0)