Configure DBContext in Entity framework ASP.NET Core – Best Practices

Configure DbContext in Entity framework

In this post, we will see how to configure DbContext in Entity framework EFCore in ASP.NET Core.

We will see high-level guidelines and best practices that can be considered in general for configuring the DBCOntext.

As we looked into our article on Repository implementation for Entity framework DbContext instance represents the Unit Of Work and Repository patterns that can be used to query from a database and perform CRUD operations.

We shall be covering the below aspects in today’s article,

What is DBContext

DBContext represents an abstraction layer around the data we are dealing with.

This abstraction exists between the data and the Business/Domain(DDD) objects of an application we are dealing with.

It allows you to access everything from the database as an Object (OOPS) with simplification and ease

DBContext not only isolates the business objects from the database access code but also provides a clean separation of concerns.

Configuring DbContext in Entity Framework is important for establishing the connection and performing efficient CRUD operations on the datastore of your choice.

Configuring the Default Database provider

This shall be the first thing we will do while configuring the DBContext instance.

It should have DbContextOptions which actually help set up required DBContext details along with the database provider to use and connection string etc.

Please do the below configuration to set the DBContext option.

Use AdDbContext() method to inject the required DBContext injected in the Service IoC container as below,

Configure DbContext in Entity framework NET Core 5 ot NET 6

Using DBContext class to use Constructor Injections for the DbContextOptions<TContext> object as below,

 public EmployeeContext(DbContextOptions<EmployeeContext> options)
            : base(options)
        {
        }

        public virtual DbSet<Employee> Employee { get; set; }



..
.

Similarly, If using the override OnConfiguring method then you can achieve the same by DBContextOptionsbuilder to initialize the DbContextOption as below,

Lifetime management of DBContext

Lifetime management of DBContext

Using DbContext with Dependency Injection,

  • Using DbContext via a dependency injection container is recommended.

  • This ensures DbContext is created as per request by the API pipeline and disposed of based on lifetime management used while registering it.

  • Add the DbContext type to the service container by using the AddDbContext method with Scoped lifetime (Recommended ).

  • Using AddDbContext(..) ensures that you are registering the DBCOntext as a scoped object. i.e every new request will use the services injected and hence the new DBContext.

 public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();
            services.AddDbContext<EmployeeContext>(options =>
            {
                options.UseSqlServer(Configuration.GetConnectionString("EmployeeDB"));
            });
        }

Using DbContext without Dependency Injection,

If not using DI due to some reason, It becomes the implementor’s responsibility to keep track of such resources and dispose of them manually instead of the compiler doing it for you (as we see above using DI).

If not using DI – then It’s recommended to use the “Using” statement for creating the resources and disposing of them after their usage.

 using (var context = new EmployeeContext())
            {
                empList = _employeeContext.Employee.AsEnumerable().Select(x => x.EmployeeId).ToList();
            }

Access DBContext in Repository or other Services

It’s better to keep the same lifetime instance for Repository/Other Custom services and DBContext to avoid any issue related to Data corruption.

Access DBContext in Repository or other Services

Define Connection Resiliency for your DBContext

The connection resiliency feature retries defaulted database commands automatically.

Use connection resiliency as it just takes a few lines of code for making your connection resilient.

Define Connection Resiliency for your DBContext

For more details: Database Connection Resiliency in Entity Framework ASP.NET Core

If dealing with multiple DBContext, then Connection resiliency needs to be defined per DBContext separately.

Concurrency of EFCore DBContext

DBContext object is not thread-safe.

Using AddDbContext(..) however, ensures that you are registering the DBContext as Scoped. i.e every new request will use the new service instance and hence the new DBContext.

So ideally concurrency is implemented per request basic avoiding any data corruption issues.

However, It should be protected from any parallel access within the same request context.

It’s the implementor’s responsibility to implement the concurrency while using it in Task/Multithreaded operations.

As good practice also please make sure to use Synchronous and Asynchronous operation properly in the code.

Concurrency of EFCore DBContext

In the above code, I marked method a method call with await as it invokes an Asynchronous operation. For more details please refer Understanding Async vs Sync programming

Client-Server query evaluation

.NET Core 3.0 onwards Entity Framework Core has blocked client-side query evaluation and recommends query execution on the server only.

If using the older version(<3.0) of EF Core please let the developer know about query evaluation support. One can configure the below warning for the same,

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(sqlConnectionString,
                 builder => builder.EnableRetryOnFailure())
                 .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));

            }

Or the same can be configured within Configure method in the StartUp.cs

Other references :

Do you have any comments or ideas or any better suggestions to share?

Please sound off your comments below.

Happy Coding !!

Summary

Today in this article we looked at guidelines around configuring the DBContext in Entity framework ASP.NET Core applications. We looked at various aspects like managing database providers, lifetime management, resiliency, and concurrency management while configuring the DBContext.



Please bookmark this page and share it with your friends. Please Subscribe to the blog to receive notifications on freshly published(2024) best practices and guidelines for software design and development.



6 thoughts on “Configure DbContext in Entity framework ASP.NET Core – Best Practices

  1. A bit late to the party, but maybe somebody will explain this to me. Why would it be recommended to inject the context? It basically assures that it’s alive throughout the entire lifetime of a request/process, even if it’s only used in a small part of it. On top of it, it means sharing the context between queries, does it not? Especially so if using repository classes, which I personally lividly hate.

    1. Hi HuggyKaze- Thanks for your query. Injecting DBContext and its life span depends purely on its configuration by the user in the IoC container. You can configure it as Transient (New instance each in a different module/class), Scoped (new instance for the whole request), or SingleTon( same instance for every request).

Leave a Reply

Your email address will not be published. Required fields are marked *