This is the base class responsible for managing database connections and provides all sorts of DB related functionality like data access methods to interact with Database. 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. The DbSet type allows EF Core to query and save instances of the specified entity to the database.
Alternatively, you could define a SaveChanges() method on all your repositories, which would just delegate to the underlying DbContext. The service method would then just call SaveChanges() on the repository itself. This would be very misleading code, as it would imply that each repository implement their own unit-of-work and can persist their changes independently of the other repositories. Which would of course be incorrect as they would in fact all use the same DbContext instance behind the scenes.
Disable Lazy Loading and Use Eager Loading for Improved Performance
In this article, we’ll explore how to create a DbContext in .NET with code examples. A DbContext represents a collection of entity sets or tables in your database. It allows us to write strongly-typed code against our database without having to deal with low-level SQL statements or having to worry about manually mapping classes to database tables. Entity Framework Core is an open-source, popular, lightweight, and flexible cross-platform ORM. In Entity Framework Core (also called EF Core), a Db context is an object that coordinates queries, updates, and deletes against your database. In the realm of Entity Framework Core, the choice of DbContext lifecycle plays a pivotal role in shaping the performance, data consistency, and resource management within your application.
The personal blog of Rowan Miller, the program manager for the Entity Framework team, is a must-read for any developer working on an Entity Framework-based application. Of course, naming this component DbContextScope means that you can’t hide the fact that you’re using Entity Framework from your services anymore. UnitOfWork is a conveniently vague term that allows you to abstract away the persistence mechanism used in the lower layers. Whether or not abstracting EF away from your service layer is a good thing is another debate that we won’t get into here.
Ambient DbContext
Coupled with a READ COMMITTED isolation level – the default on SQL Server – this suits the needs of most business transactions. This is especially the case if you rely on optimistic concurrency to detect and avoid conflicting updates. Note that you can’t re-use the same DbContext instance across multiple business transactions if you rely on pessimistic concurrency. A very common scenario where the lifetime of the DbContext instance can be maintained independently from the lifetime of business transactions is in the case of web applications.
- If you’re going to use it as a basic ORM and won’t use any of the features that it provides on top of its ORM capabilities, you might be better off using a lightweight ORM library such as Dapper.
- But the class should and must be derived from the DbContext class and exposes DbSet properties for the types you want to be part of the model.
- It won’t be long until you need to create command-line utilities for your support team to execute ad-hoc maintenance tasks or Windows Services to handle scheduled tasks and long-running background operations.
- In this article, we’ll explore how to create a DbContext in .NET with code examples.
- Tread carefully when using this as it can create tricky issues and quickly lead to a maintenance nightmare.
- This EF behaviour can result in subtle bugs as it is possible to be in a situation where queries may unexpectedly return stale or incorrect data.
By injecting it into whatever layer implement your data access, you’re making that layer, and by extension all the layers above which would be pretty much the entire application, stateful. You then need to configure your DI container to create an instance of the DbContext with an appropriate lifetime on object graph creation. A common advice you’ll find is to use a PerWebRequest lifetime for web apps and PerForm lifetime for desktop apps. NHibernate users will be very familiar with this approach as the ambient context pattern is the predominant approach used in the NHibernate world to manage NH’s Session (NHibernate’s equivalent to EF’s DbContext). NHibernate even comes with built-in support for this pattern, which it calls contextual sessions.
Database Connections
In practice however, and unless you choose to explicitly manage the database connection or transaction that the DbContext uses, not calling DbContext.Dispose() won’t cause any issues as Diego Vega, a EF team member, explains. It won’t be long until you need to create command-line utilities for your support team to execute ad-hoc maintenance tasks or Windows Services to handle scheduled tasks and long-running background operations. When this happens, you want to be able to reference the assembly that contains your services and just use any service you need from your console or Windows Service application.
The following code snippet illustrates how you can use eager loading using your custom DbContext instance. “Even when it is important to follow the Persistence Ignorance principle for your Domain model, you should not ignore persistence concerns. It is still very important to understand the physical data model and how it maps to your entity object model. In other words, if your entities are persistence ignorant, they shouldn’t bother about how they’re persisted, created, retrieved, updated, or deleted. The concept of a DbContext has been around since the first version of the Entity Framework was released.
Managing DbContext the right way with Entity Framework 6: an in-depth guide
The only reliable method to correctly manage the database transaction lifetime with NHibernate is to wrap all your service methods in an explicit database transaction. This is what you’ll see done in pretty much what is entity framework every NHibernate-based application. With this approach, the top-level service method not only creates the DbContext to use for the current business transaction but it also registers it as the ambient DbContext.
When using DbContext in EF Core, there are a few best practices to follow in order to maximize the efficiency and effectiveness of working with EF Core in your applications. It would help if you did not use Dependency Injection for your DbContext instance in domain model objects. This rule aims to keep the code clean and DRY and make it easier to test. Hence, inject the actual instance of the class that has a dependency if you want to use dependency injection. So, instead of injecting an instance of DbContext, you should inject an instance of type IUnitOfWork or another class that contains other dependencies that the specified object type can use. It would help if you did not dispose of DbContext objects in most cases.
Defining a DbContext Derived Class
Mark contributions as unhelpful if you find them irrelevant or not valuable to the article. Override OnModelCreating method to seed Employee and Department data. We pass the DbContextOptions to the base DbContext class constructor using the base keyword as shown below. By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy. 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.
It also muddies your method contracts as your service method are now forced to ask for a parameter that they neither need nor use but require purely to satisfy the dependency of a downstream method. There’s unfortunately no built-in way to override this isolation level. If you’d like to use another isolation level, you must start and manage the database transaction yourself.
Autocommit (or Implicit) transactions will use whatever default transaction isolation level the database engine has been configured to use (READ COMMITTED by default for SQL Server). As a result, it’s advisable to avoid managing the lifetime of DbContext instances separately from business transactions. Instead, each service method (i.e. each business transaction) should create its own DbContext instance and dispose it at the end of the business transaction (i.e. before returning). By doing this, you’re loosing pretty much every feature that Entity Framework provides via the DbContext, including its 1st-level cache, its identity map, its unit-of-work, and its change tracking and lazy-loading abilities.