Digging deeper into DbContext in Entity Framework Core (2024)

.NET Programming

By Joydip Kanjilal, Contributor, InfoWorld |

EF Core allows you to instantiate a DbContext in several ways. Learn when and how to use these different approaches in your ASP.NET Core applications.

Digging deeper into DbContext in Entity Framework Core (2)

Entity Framework Core is an object-relational mapper, or ORM, that isolates your application’s object model from the data model. That allows you to write code that performs CRUD operations without worrying about how the data is stored. In other words, you work with the data using familiar .NET objects.

In Entity Framework Core, theDbContext connects thedomain classes to the database by acting as a bridge between them. You can take advantage of the DbContext to query data in your entities or save your entities to the underlying database.

I’ve discussed the basics of DbContext in a previous article. In this article we’ll dive into DbContext in a little more detail, discuss the DbContext lifetime, and offer some best practices for using DbContext inEntity Framework Core. EF Core allows you to instantiate a DbContext in several ways. We’ll examine some of the options.

To use 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 an ASP.NET Core Web API project in Visual Studio 2022

To create an ASP.NET Core 8 Web API project in Visual Studio 2022, follow the steps outlined below.

  1. Launch the Visual Studio 2022 IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.NET Core Web API” 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. Optionally check the “Place solution and project in the same directory” check box, depending on your preferences.
  7. Click Next.
  8. In the “Additional Information” window shown next, select “.NET 8.0 (Long Term Support)” as the framework version and make sure the “Use controllers” box is unchecked. We’ll be using minimal APIs in this project.
  9. Elsewhere in the “Additional Information” window, leave the “Authentication Type” set to “None” (the default) and ensure the check boxes “Enable Open API Support,” “Configure for HTTPS,” and “Enable Docker” remain unchecked. We won’t be using any of those features here.
  10. Click Create.

We’ll use this ASP.NET Core Web API project to work with DbContext in the sections below.

What is DbContext? Why is it needed?

When working with Entity Framework Core, the DbContext represents a connection session with the database. It works as a unit of work, enabling developers to monitor and control changes made to entities before saving them to the database. We use the DbContext to retrieve data for our entities or persist our entities in the database.

The DbContext class in EF Core adheres to the Unit of Work and Repository patterns. It provides a way to encapsulate database logic within the application, making it easier to work with the database and maintain code reusability and separation of concerns.

The DbContext in EF Core has a number of responsibilities:

  • Managing connections
  • Querying data from the database
  • Saving data to the database
  • Concurrency control
  • Change tracking
  • Caching
  • Transaction management

The DbContext lifetime

The DbContext class in Entity Framework Core plays a crucial role in facilitating the connection between the application and the database, providing support for data access, change tracking, and transaction management. The lifetime of a DbContext instance starts when it is instantiated and ends when it is disposed.

Here is the sequence of events in a typical unit of work using EF Core:

  1. A DbContext instance is created.
  2. Entities are tracked using this instance.
  3. Changes are made to the tracked entities.
  4. The SaveChanges method is invoked to store the entities in memory to the underlying database.
  5. The DbContext object is disposed or garbage-collected when it is no longer needed by the application.

Avoid using DbContext in using statements

A DbContext instance should be disposed when it is no longer needed to free up any unmanaged resources and prevent memory leaks. However, it is not a recommended practice to dispose off DbContext instances explicitly or to use DbContext within a using statement.

Here’s why you should not dispose of your DbContext instances:

  • When you dispose of a DbContext object, you may have one or more entities that cannot be saved to the database.
  • Instantiating and releasing DbContext objects can be expensive, mainly when setting up a new database connection.
  • Removing the DbContext inside a using block after each usage may result in avoidable overhead and reduced performance.
  • Disposing the DbContext object when database modifications are pending or when you still expect to use the context might lead to problems or unexpected behavior.
  • Prematurely disposing of the DbContext instances may interfere with change tracking, making further updates or queries difficult or impossible.

Instead of using using blocks to dispose of the DbContext instances in your application, consider taking advantage of dependency injection to manage their lifetime. Using dependency injection will ensure that the DbContext is created and disposed of appropriately, depending on the life cycle of the application or the scope of the operation.

Create a new DbContext instance in EF Core

There is no specific rule for creating a DbContext instance. The requirements of your application should determine which approach you take. Each of the approaches illustrated below has its specific use cases—none of them is better than the others.

You can extend the DbContext class in EF Core to create your own DbContext class as shown below.

public class IDGDbContext : DbContext{ public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { }}

Similarly, you could instantiate a DbContextOptionsBuilder class and then use this instance to create an instance of DbContextOptions. This DbContextOptions instance could then be passed to the DbContext constructor. This approach helps you explicitly create a DbContext instance.

Use dependency injection to create DbContext instances

Alternatively, you can create DbContext instances via dependency injection (DI) by configuring your DbContext instance using the AddDbContext method as shown below.

services.AddDbContext<IDGDbContext>( options => options.UseSqlServer("name=ConnectionStrings:DefaultConnection"));

You can then take advantage of constructor injection in your controller to retrieve an instance of DbContext as shown below.

public class IDGController{ private readonly IDGDbContext _dbContext; public IDGController(IDGDbContext dbContext) { _dbContext = dbContext; }}

Typically, an HTTP request-response cycle represents a unit of work in web applications. With DI, we are able to create a DbContext instance for each request and dispose of it when that request terminates.

I prefer using a DI container to instantiate and configure DbContext because the DI container manages the DbContext instances and lifetimes for you, relieving you of the pain of managing these instances explicitly.

Initialize DbContext in the OnConfiguring method

A third option is to create a DbContext instance by overriding the OnConfiguring method in your custom DbContext class. You can then take advantage of the DbContext constructor to pass configuration information, such as a connection string.

The code snippet below shows how you can initialize DbContext in the OnConfiguring method of your custom DbContext class.

public class IDGDbContext : DbContext{ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { optionsBuilder.UseSqlServer("Specify your database connection string here."); }}

Register a factory to create a DbContext instance

You can also create an instance of DbContext using a factory. A factory comes in handy when your application needs to perform multiple units of work within a particular scope.

In this case, you can use the AddDbContextFactory method to register a factory and create your DbContext objects as shown in the code snippet given below.

services.AddDbContextFactory<IDGDbContext>( options => options.UseSqlServer("Specify your database connection string here."));

You can then use constructor injection in your controller to construct DbContext instances as shown below.

private readonly IDbContextFactory<IDGDbContext> _dbContextFactory;public IDGController(IDbContextFactory<IDGDbContext> dbContextFactory){ _dbContextFactory = dbContextFactory;}

You can turn on sensitive data logging to include application data when exceptions are logged in your application. The following code snippet shows how this can be done.

optionsBuilder .EnableSensitiveDataLogging() .UseSqlServer("Specify your database connection string here.");

Finally, note that multiple parallel operations cannot be executed simultaneously on the same DbContext instance. This refers to both the parallel execution of async queries and any explicit use of multiple threads of the instance simultaneously. Therefore, it is recommended that parallel operations be performed using separate instances of the DbContext. Additionally, you should never share DbContext instances between threads because it is not thread-safe.

Next read this:

  • Why companies are leaving the cloud
  • 5 easy ways to run an LLM locally
  • Coding with AI: Tips and best practices from developers
  • Meet Zig: The modern alternative to C
  • What is generative AI? Artificial intelligence that creates
  • The best open source software of 2023

Related:

  • Microsoft .NET
  • C#
  • Database
  • Software Development

Joydip Kanjilal is a Microsoft MVP in ASP.NET, as well as a speaker and author of several books and articles. He has more than 20 years of experience in IT including more than 16 years in Microsoft .NET and related technologies.

Follow

Copyright © 2024 IDG Communications, Inc.

Digging deeper into DbContext in Entity Framework Core (2024)

FAQs

What is DbContext in .net core? ›

A DbContext instance represents a session with the database and can be used to query and save instances of your entities. DbContext is a combination of the Unit Of Work and Repository patterns.

How to mock DbContext in .NET core? ›

Here, first, we build a mock DbSet using the fake employee list. After that, we set up the DbContext to return this DbSet . This way, we can test the GetEmployees() method by using a mock DbSet . Here, we create a mock DbSet and set up the FindAsync() method.

What is DbSet in Entity Framework? ›

A DbSet represents the collection of all entities in the context, or that can be queried from the database, of a given type. DbSet objects are created from a DbContext using the DbContext. Set method. C# Copy.

How to create DbContext in .net core 5? ›

Adding DbContext to . NET Core Web API
  1. Create a new C# class AppDbContext (Choose any name you want)
  2. Inherit from the base class DbContext.
  3. Inject DbContextOptions<AppDbContext> into constructor and pass it to the base class.
  4. Define the DbSets of your Models.
Mar 29, 2021

Is DbContext scoped or singleton? ›

To summarize, DbContext is Scoped while DbContextFactory is Singleton and they both need a DbContextOptions which is Scoped by default.

Should I use DbContext or DbContextFactory? ›

The DbContext is a singleton class that represents the gateway to all data access, and therefore should not be instantiated more than once. If you need multiple database connections or have multiple active contexts operating in parallel, then use the DbContextFactory class instead.

What is the difference between DbContext and ObjectContext? ›

DbContext is nothing but an ObjectContext wrapper, we can say it is a lightweight alternative to the ObjectContext. DbContext can be used for DataBase first, code first and model first development. DbContext mainly contains a set of APIs that are very easy to use. The API is exposed by ObjectContext.

What is the lifetime of DbContext? ›

The lifetime of a DbContext begins when the instance is created and ends when the instance is disposed. A DbContext instance is designed to be used for a single unit-of-work. This means that the lifetime of a DbContext instance is usually very short.

How to execute raw SQL query using DbContext in Entity Framework Core? ›

EF Core ExecuteSql

The DbContext exposes a Database property which includes a method called ExecuteSql . This method returns an integer specifying the number of rows affected by the SQL statement passed to it. Valid operations are INSERT , UPDATE , and DELETE . The method is not used for returning entities.

What is the best mocking framework for NET Core? ›

Moq (pronounced "Mock-you" or just "Mock") is the only mocking library for . NET developed from scratch to take full advantage of . NET Linq expression trees and lambda expressions, which makes it the most productive, type-safe and refactoring-friendly mocking library available.

How to speed up Entity Framework Core? ›

More ways to improve EF Core Performance...
  1. Use projections.
  2. Use Async Methods.
  3. Avoid non cancellable queries.
  4. Include only necessary tables.
  5. For bulk processing, use chunks.
  6. Use Any method of LINQ for filters.
  7. Use DbContextPool with DB contexts.
  8. For multiple filters use IQueryable.
Aug 15, 2023

What is the difference between DbContext and DbSet? ›

DbSet definition

A non-generic version of DbSet<TEntity> which can be used when the type of entity is not known at build time. Let's look at these, a DbContext contains one or more DbSet e.g. a Blog as a master table and Post as a child table to Blog table.

Why do we use DbContext in C#? ›

A DbContext instance represents a combination of the Unit Of Work and Repository patterns such that it can be used to query from a database and group together changes that will then be written back to the store as a unit.

How to create DbContext in Entity Framework code first? ›

Add model class into project. Create “CodeFirstContext” class, which will inherit “DbContext” (DbContext exist inside System. Data. Entity namespace), this derives context class and represents session with database and helps us to make transactions with database like save the data or fetch the data from database.

How to initialize DbContext? ›

The DbContext itself and any dependencies in its constructor need to be registered as services in the application's service provider. This can be easily achieved by having a constructor on the DbContext that takes an instance of DbContextOptions<TContext> as an argument and using the AddDbContext<TContext> method.

Top Articles
Latest Posts
Article information

Author: Carlyn Walter

Last Updated:

Views: 6055

Rating: 5 / 5 (70 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Carlyn Walter

Birthday: 1996-01-03

Address: Suite 452 40815 Denyse Extensions, Sengermouth, OR 42374

Phone: +8501809515404

Job: Manufacturing Technician

Hobby: Table tennis, Archery, Vacation, Metal detecting, Yo-yoing, Crocheting, Creative writing

Introduction: My name is Carlyn Walter, I am a lively, glamorous, healthy, clean, powerful, calm, combative person who loves writing and wants to share my knowledge and understanding with you.