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();
And the async equivalent:
// Asynchronous query
var customers = await context.Customers.ToListAsync();
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
}
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 (1)
EF Core + SQL server. Performance Bug to using methods async. Please check is. github.com/dotnet/SqlClient/issues...