How to improve EF Core 7 performance

How to improve EF Core 7 performance

Entity Framework Core is an open source ORM (object-relational mapping) framework that bridges the gap between the object model of your application and the data model of your database. EF Core makes life simpler by allowing you to work with the database using .NET objects, instead of having to write weird data access code.

EF Core lets you write code to execute CRUD actions (create, read, update, and delete) without understanding how the data is persisted in the underlying database. Using EF Core, you can more easily retrieve entities from the data store, add, change, and delete entities, and traverse entity graphs.

>>You can improve data access performance in Entity Framework Core in several ways. These include enabling eager loading, disabling lazy loading, using streaming instead of buffering, and disabling change tracking. In this article, we will explore some of the tips and tricks that can help you improve the performance of your ASP.NET Core 7 applications that make use of EF Core 7.<<

To work with the code examples provided in this article, you should have Visual Studio 2022 installed in your system. If you don’t already have a copy, you can download Visual Studio 2022 here.

Create a console application project in Visual Studio

First off, let’s create a .NET Core console application project in Visual Studio. Assuming Visual Studio 2022 is installed in your system, follow the steps outlined below to create a new .NET Core console application project.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “Console App (.NET Core)” from the list of templates displayed.
  4. Click Next.
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Click Next.
  7. In the “Additional information” window shown next, choose “.NET 7.0 (Standard Term Support)” as the Framework version you want to use.
  8. Click Create.

We’ll use this console project to work with Entity Framework Core in the subsequent sections of this article.

EF Core performance best practices

You can help EF Core perform these data access operations more speedily by taking advantage of a few best practices. We’ll discuss five of these best practices below.

Disable change tracking for read-only scenarios

Whenever you query entities in your DbContext, the context tracks the returned objects so that you can alter them and preserve the changes. If the query is a read-only query, i.e., if no changes will be made to the returned data, then the context is not required to perform that task. You should disable change tracking if it is not required.

You can disable change tracking for individual queries by including the AsNoTracking method in the query. When the AsNoTracking method is used, EF Core will skip the extra effort of tracking the entities, thereby improving performance (especially for queries involving large numbers of entities).

Most importantly, you do not need change tracking when you only intend to retrieve data in your application. In other words, if you only want to retrieve data from the data context, without inserting, updating, or deleting data, then you don’t need this feature to be turned on. You can disable object tracking by adding the following code to your data context class.

ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;

The bottom line is that queries that use AsNoTracking will run faster than queries that don’t use it. However, remember that you must never use AsNoTracking in queries that insert, edit, or delete entities. Furthermore, if you need to insert, edit, or delete data using the data context, you should avoid specifying the QueryTrackingBehavior at the data context level.

Retrieve only the data you need

When dealing with massive volumes of data, you should strive to retrieve only the required records for the specific query. When fetching data, you should use projections to pick just the required fields. You should avoid retrieving unnecessary fields. The following code snippet shows how to obtain data in a paged fashion. Notice how the beginning page index and page size have been used to choose just the required data.

int pageSize = 50, startingPageIndex = 1;
var dataContext = new OrderProcessingDbContext();
var data = dataContext.Orders.Take(pageSize)
.Skip(startingPageIndex * pageSize)
.ToList();

Split your large data context into many smaller data contexts

The data context in your application represents your database. Hence, you may wonder whether the application should have only one or more data contexts. In Entity Framework Core, the startup time of a large data context represents a significant performance constraint. As a result, instead of using a single vast data context, you should break the data context into numerous smaller data contexts.

Ideally, you should only have one data context per module or unit of work. To use multiple data contexts, simply create a new class for each data context and extend it from the DbContext class.

Disable lazy loading

Lazy loading is a feature that eliminates the need to load unnecessary related entities (as in explicit loading) and seems to remove the developer from dealing with related entities entirely. Because EF Core is adept at automatically loading related entities from the database when accessed by your code, lazy loading seems like a nice feature.

However, lazy loading is especially prone to generating unnecessary additional round trips, which could slow down your application. You can turn off lazy loading by specifying the following in your data context:

ChangeTracker.LazyLoadingEnabled = false;

Use DbContext pooling

An application typically has multiple data contexts. Because DbContext objects may be costly to create and dispose of, EF Core offers a mechanism for pooling them. By pooling, DbContext objects are created once, then reused when needed.

Using a DbContext pool in EF Core can improve performance by reducing the overhead involved in building and disposing of DbContext objects. Your application may also use less memory as a result.

The following code snippet illustrates how you can configure DbContext pooling in the Program.cs file.

builder.Services.AddDbContextPool<MyDbContext>(options => options.UseSqlServer(connection));

This article provided a discussion of best practices that can be adopted to improve data access performance in EF Core. Of course, every application has different data access requirements and characteristics. You should benchmark your EF Core performance before and after you apply these changes to assess the results for your specific application. An excellent tool for the task is BenchmarkDotNet, which you can read about in a previous post.

Add a Comment