Optimize your use of Entity Framework by following best practices that enhance performance and maintainability. These guidelines cover everything from efficient querying and data manipulation to leveraging migrations and in-memory providers, ensuring your application runs smoothly and effectively.
Entity Framework allows you to provide a strongly typed object framework (ORM) over your database. This helps abstract the database away allowing it to be replaced with other technologies as needed.
It's expensive retrieving data from a database, as such it's important to only ask for the rows you require when getting data.
When you cast IQueryable to IEnumerable and then query the data from there, Entity Framework must collect the data at the point you do the cast. This can result in very significant extra database load, and extra processing on the client side.
NOTE: Using .AsEnumerable() achieves the same effect.
One of EF Core's best features is the fact it tracks any changes you make to entities after you retrieve them. However this comes with a cost, if the data is only being read and the returned entities will never be modified then you can use the AsNoTracking method to inform EF Core not to bother tracking changes.
This results in fairly significant memory and CPU improvements on the client side.
When retrieving data it's much more efficient to only collect the data you need. It saves computation and IO on the database and also saves memory and CPU on the calling side.
The Update method on an entity in EF Core marks all of its fields as dirty. This will result in all the fields being written back to the database.
Often developers will include all the related entities in a query to help with debugging. Always remember to take these out. They cause excessive database load.
Pagination can be expensive if all the pages are retrieved from the database before grabbing the relevant page. It's much more efficient to get only the page number requested back from the database.
TagWith adds comments to the generated SQL. This makes it easier to identify queries when they run on the database.
To avoid embarrassing failures in Production, it is important to ensure that your development systems are as similar as possible to what's expected in Production.
Benchmarking your system's performance is important. This is making sure you have information on how your system performs with a known set of data and load.
There are plenty of good benchmarking tools for .Net solutions.
Databases are slow at doing bulk updates. It's generally significantly faster to break bulk processing down into manageable chunks. It also avoids other database users experiencing significant blocking issues.
Raw SQL comes with risks but sometimes it is the best solution.
Most enterprise applications require a database to store data. Once you have a database you need a way to manage the schema.
Entity Framework Code First Migrations allow you to update a database schema rather than recreate it from scratch. This is useful when you have a production database that you want to keep, but you want to make changes to the schema.
When testing code that depends on Entity Framework Core, the challenge often lies in how to effectively mock out the database access. This is crucial for focusing tests on the functionality surrounding the DB access rather than the database interactions themselves. The EF Core In-Memory provider is a tool designed to address this need.
Some older projects .NET Framework project will have EDMX instead of modern DbContext first introduced in Entity Framework 4.1, which first introduced DbContext and Code-First approach back in 2012, replacing the ObjectContext that EDMX used for Database-First approach.
In this rule, we’ll use ObjectContext and Entities interchangeably. ObjectContext is the base class that is used by the generated class, which will generally end with Entities (e.g. DataEntities).
The rule is focusing on .NET 8+ as the support for .NET Framework projects and Nuget was added back, which makes a staged migration a lot more feasible. Most, if not all, are still applicable for .NET 7 as well.