Blog

Home / Blog

How to improve data access performance in EF Core

Billy Yann
Data Scientist
Deep learning and machine learning specialist, well-versed with experience in Cloud infrastructure, Block-chain technologies, and Big Data solutions.
September 08, 2023


The popular Entity Framework data access technology is available in a lightweight, extensible, and cross-platform version called Entity Framework (EF) Core.

As an object-relational mapper (O/RM), EF Core can:

1. allows .NET developers to use.NET objects to interact with a database.

2. eliminates the necessity for writing the majority of the data-access code that is normally required.

3. Numerous database engines are supported by EF Core.

Data access with EF Core is carried through by use of a model. Entity classes and a context object that symbolises a database session make up a model. Data can be saved and queried via the context object.

To manually match a model to the database.

Use EF Migrations to build a database from a model after it has been constructed. Migrations enable the database to evolve as the model does.

Language Integrated Query (LINQ) is used to get instances of your entity classes from the database. Instances of your entity classes are used to create, delete, and modify data in the database.

Methods for EF Core Development

EF Core supports two methods of development. 1) Database-First, and 2) Code-First. Because EF Core 2.0 does not enable the visual designer or wizard for DB model, it primarily supports the code-first method while offering little assistance for the database-first approach.

According to the conventions and configuration specified in your domain classes, EF Core API builds the database and tables utilising migration in the code-first method. When using Domain Driven Design (DDD), this strategy is helpful.

When employing the database-first strategy, EF Core API uses EF Core commands to build the domain and context classes on top of your existing database. Due to the lack of a visual designer or wizard, EF Core only offers limited support for this.

 Entity Framework Core is the updated version of Entity Framework for.NET Core applications, replacing Entity Framework 6. Being new, EF Core is not yet as developed as EF 6.

How to enhance the speed of EF Core's data access

An open source ORM (object-relational mapping) framework called Entity Framework Core (EF Core) connects the data model of your database with the object model of your application. With EF Core, you can work with the database using.NET objects rather of needing to write data access code, which makes life easier.

So you can write code to perform CRUD operations (create, read, update, and delete) without being aware of how the data is stored in the underlying database, thanks to EF Core. Working directly in C# makes it simpler to obtain entities from the data store, add, update, and delete entities, as well as navigate entity graphs. You can use eager loading or lessen the number of database round trips your queries take to boost the performance of data access in EF Core.

Apply indexes correctly.

The primary determinant of whether a query executes quickly or slowly is whether it makes good use of indexes when necessary. Since databases are frequently used to store large amounts of data, queries that traverse whole tables are frequently the cause of major performance problems. Because it isn't always evident whether a given query will use an index or not, indexing problems might be difficult to identify.

 Finding a sluggish query and then using your database's preferred tool to look at its query plan can help you find indexing problems. The query plan shows whether the query employs an index or explores the entire table.

In general, using indexes and identifying performance problems with them don't require special understanding of EF; general database knowledge about indexes is applicable to both EF-using and non-EF-using applications.

Indexes speed up searches, but because they must be maintained current, they also slow down updates. Avoid creating unnecessary indexes and think about utilising index filters to restrict the index to a subset of the rows to minimise this overhead.

Depending on the ordering, composite indexes can speed up queries that filter on several columns as well as queries that do not filter on all of the columns in the index.

A simple index cannot be utilised when filtering by an expression over a column in a query. For your expression, you can establish a stored persistent column and build an index over it. Expression indexes, which can be used directly to speed up queries filtering by any expression, are also supported by several databases.

The configuration of indexes might vary depending on the database, and many EF Core providers provide this via the Fluent API. The SQL Server provider, for instance, enables you to customise an index's clustering status and fill factor. For more details, go to the documentation provided by your provider.

When testing, test databases often contain little data, so everything works well, but when real-world data is retrieved, performance problems suddenly arise. In this case, limiting the number of results is generally a good idea.

At a minimum, your UI could show a message indicating that more rows may exist in the database (and allow retrieving them in some other manner).To implement pagination, your UI would show only a certain number of rows at a time and allow users to advance to the next page as needed; see the next section for more details.

You require only project properties.

EF It's quite simple to find entity instances with Core and use them in code. However, searching entity instances frequently causes your database to retrieve more information than is necessary.

To a maximum resultset size

It is impossible to predict how much data will be loaded from the database, how much memory the results will consume, and how much additional load will be produced when processing these results (for example, by sending them to a user browser over the network). This is because the number of rows returned depends on the actual data in your database.

Importantly, test databases usually have sparse amounts of data, so everything functions normally when testing but suddenly exhibits performance issues when the query is executed on real-world data and many rows are returned. As a result, considering outcomes limitation is typically worthwhile.

Your user interface (UI) may at the very least provide a warning indicating that more rows might be there in the database (and allow accessing them in another way). Implementing pagination, where your UI only displays a specific amount of rows at a time, would be a comprehensive solution.

Streamlined pagination

Pagination is the practise of retrieving results in pages as opposed to all at once; it is frequently used for large resultsets and involves displaying an interface that enables users to browse to the results' next or previous page. The Skip and Take operators (OFFSET and LIMIT in SQL) are frequently used to perform pagination with databases; while this is an understandable implementation, it is also incredibly ineffective. Instead of hopping to random pages, think about employing keyset pagination, which permits moving one page at a time.

When loading linked entities, avoid cartesian explosion.

By using JOINs in a single query, all connected entities in relational databases are loaded. When a normal blog has several related topics, the information in the rows for those posts will be duplicated throughout the blog. The so-called "Cartesian explosion" problem is brought on by this duplication. The quantity of duplicate data may increase as more one-to-many relationships are loaded, which could have a negative impact on how well your application runs.

By loading the associated entities using separate queries, "split queries" in EF allow avoiding this effect.

When it's achievable, immediately load linked entities.

When working with related entities, we typically have a predetermined list of what has to be loaded. A good example would be loading a specific set of blogs along with all of their posts. In these situations, eager loading is always preferable so that EF can collect all the necessary data in a single roundtrip. You can restrict which related entities you want to load using the filtered inclusion feature, keeping the loading process eager and hence manageable in a single roundtrip.

 In other cases, we might not be aware of which linked entity we'll require before receiving its principal entity. For instance, in order to determine whether we are interested in a blog's posts before loading it, we may need to contact another data source, potentially a webservice. In these circumstances, related entities can be fetched individually and added to the Blog's Posts navigation using explicit or lazy loading. Due to the fact that these methods aren't eager, they necessitate additional roundtrips to the database, which causes slowdown. Depending on your particular situation, it might be more effective to always load all Posts rather than making the extra roundtrips and only obtaining the Posts you specifically require.

Conclusion

In summary, improving data access speed within Entity Framework Core (EF Core) relies on a blend of strategic decisions, including choosing efficient data retrieval techniques, employing intelligent indexing, and implementing pagination. By thoughtfully assessing your application's requirements and the characteristics of your data, you can greatly enhance performance and provide users with a more seamless experience when utilizing EF Core.