DbContext in Entity Framework Core

DbContext Class in Entity Framework Core

In this article, I will discuss the DbContext Class in Entity Framework Core. Please read our previous article, discussing How to Install Entity Framework Core in .NET Applications. The DbContext class is one of the important classes in the Entity Framework core. At the end of this article, you will understand the significance of the DbContext class in the Entity Framework Core.

Note: We will work with the example we created in our previous article and discuss How to Install Entity Framework Core in our .NET Application.

What is the DbContext Class in EF Core?

According to MSDN, an instance of DbContext 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.

The DbContext class is an integral part of the Entity Framework. The DBContext Class in Entity Framework Core is used by our application to interact with the underlying database. This class manages the database connection and performs CRUD Operations with the underlying database. The DbContext in Entity Framework Core Performs the following tasks:

  • Object Set Representation: DbContext represents a session with the database that allows querying and saving of entity classes via DbSet<TEntity> properties for each entity type in the model.
  • Change Tracking: When retrieving data from the database using the DbContext, the changes made to that data are tracked by the DbContext. If any modifications, the entity’s properties are updated, DbContext keeps track of those changes. This enables EF Core to generate appropriate SQL statements to reflect the database changes accurately.
  • Database Operations: Using methods on DbContext, such as SaveChanges(), we can insert, update, or delete records in the database. That means the changes we make to our entities will be updated in the database when we call the SaveChanges() method of the DbContext object.
  • Configuration: The DbContext allows for the configuration of the database connection. It also tells how models are mapped to database schemas, caching policies, etc. We need to do this by overriding the OnConfiguring or OnModelCreating methods in our DbContext class (A class that is inherited from the DbContext class).
  • Querying: DbContext allows us to use LINQ to construct database queries that are automatically translated into SQL queries based on the database provided and will be executed on the corresponding database.
  • Lazy Loading: The DbContext class is also responsible for enabling lazy loading, which automatically loads the related data from the database when the navigation property is being accessed.
  • Caching: Remember to use the DbContext to perform first-level caching by default. This means that if you request the same data multiple times while the DbContext instance is active, it will return the cached version of the data instead of querying the database again. This can greatly improve performance if you need to access the same data repeatedly.
  • Unit of Work: DbContext acts as a unit of work pattern, batching all database DML operations into a single transaction to ensure data consistency. That means that by using DbContext, we can also implement transactions.
  • Connection Management: DbContext manages database connections, i.e., it opens and closes the database connection as and when needed and handles transactions for batch operations. Batch operation means executing multiple SQL Statements.
  • Migrations: The DbContext plays an important role in creating and managing database migrations, which are a way to manage database schema changes.
  • Relationship Management: DbContext manages relationships (one-to-one, one-to-many, and many-to-many) between entities and supports navigation properties for foreign key relationships in the database.
  • Database Provider Agnosticism: When using DbContext, your code will be compatible with multiple databases (SQL Server, PostgreSQL, SQLite) regardless of the specific database provider. So, our code will be the same irrespective of the database provider and the backend database.
Example to Understand DbContext Class in Entity Framework Core:

Let us understand the need and use of the DbContext Class with an example. At the root directory of your project, create a folder and name it as Entities. Then, inside this folder, create two class files named Student.cs and Standard.cs.

So, create a class file within the Entities folder named Student.cs, and then copy and paste the following code. As you can see, here, we are creating the Student class with a few scalar properties and one Reference Navigation property called Standard, which makes the relationship between Student and Standard entities one-to-one. In the next step, we are going to create the Standard entity.

using Microsoft.EntityFrameworkCore.Metadata.Internal;
using System.ComponentModel.DataAnnotations.Schema;

namespace EFCoreCodeFirstDemo.Entities
{
    public class Student
    {
        public int StudentId { get; set; }
        public string? FirstName { get; set; }
        public string? LastName { get; set; }
        public DateTime? DateOfBirth { get; set; }

        [Column(TypeName = "decimal(18,4)")]
        public decimal Height { get; set; }

        [Column(TypeName = "decimal(18,4)")]
        public float Weight { get; set; }
        public virtual Standard? Standard { get; set; }
    }
}

Next, create another class file within the Entities folder named Standard.cs, and then copy and paste the following code. As you can see, here, we are creating the Standard class with few scalar properties and one collection Navigation property called Students, which makes the relationship between Standard and Student entities one-to-many.

namespace EFCoreCodeFirstDemo.Entities
{
    public class Standard
    {
        public int StandardId { get; set; }
        public string? StandardName { get; set; }
        public string? Description { get; set; }
        public ICollection<Student>? Students { get; set; }
    }
}

Now, we are done with the initial domain classes for our application. Later, as we progress, we will add more domain classes to this example.

How to Create a DbContext Class in Entity Framework Core?

The main class that coordinates Entity Framework Core functionality for a given data model is the database context class, which allows to query and save data. The Entity Framework Core Code-First Approach requires a user-defined context class, which should be derived from the DbContext class.

To use the DbContext class in our .NET Application, we must create a class derived from the DbContext class. The DbContext class is present in Microsoft.EntityFrameworkCore namespace. The Entity Framework Core DbContext class includes a property, i.e., DbSet<TEntity>, for each entity in your application.

So, create a class file within the Entities folder named EFCoreDbContext.cs and then copy and paste the following code into it. You can give any name for your context. 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. For example, Student and Standard domain classes in this case. The DbSet is a collection of entity classes (i.e., entity set). Here, we have given the property name in the plural form of the entity name, like Students and Standards, as Microsoft recommends. The DbContext class belongs to Microsoft.EntityFrameworkCore namespace.

using Microsoft.EntityFrameworkCore;
namespace EFCoreCodeFirstDemo.Entities
{
    public class EFCoreDbContext : DbContext
    {
        //Constructor calling the Base DbContext Class Constructor
        public EFCoreDbContext() : base()
        {
        }

        //OnConfiguring() method is used to select and configure the data source
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            //use this to configure the contex
        }

        //OnModelCreating() method is used to configure the model using ModelBuilder Fluent API
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            //use this to configure the model
        }

        //Adding Domain Classes as DbSet Properties
        public DbSet<Student> Students { get; set; }
        public DbSet<Standard> Standards { get; set; }
    }
}

As you can see in the above code, the EFCoreDbContext class is derived from the DbContext class and contains the DbSet<TEntity> properties of Student and Standard type. The parameterless constructor of our context class is called the base DbContext Class constructor. It also overrides the OnConfiguring and OnModelCreating methods. We must create an instance of the EFCoreDbContext class to connect to the database and save or retrieve Student or Standard data.

The OnConfiguring() method allows us to select and configure the data source to be used with a context using DbContextOptionsBuilder. In our upcoming article, we will discuss more about this method.

The OnModelCreating() method allows us to configure the model using ModelBuilder Fluent API. Again, in our upcoming article, we will discuss more about this method.

Note: we have included two model classes as DbSet properties, and the entity framework core will create two database tables for the above two model classes with the required relationships.

DbContext Methods in Entity Framework Core:
  1. Add: Adds a new entity to DbContext with an Added state and starts tracking it. This new entity data will be inserted into the database when SaveChanges() is called.
  2. AddAsync: Asynchronous method for adding a new entity to DbContext with Added state and starts tracking it. This new entity data will be inserted into the database when SaveChangesAsync() is called.
  3. AddRange: Adds a collection of new entities to DbContext with Added state and starts tracking it. This new entity data will be inserted into the database when SaveChanges() is called.
  4. AddRangeAsync: Asynchronous method for adding a collection of new entities, which will be saved on SaveChangesAsync().
  5. Attach: Attaches a new or existing entity to DbContext with an Unchanged state and starts tracking it. In this case, nothing will happen when we call the SaveChanges method, as the entity state is not modified.
  6. AttachRange: Attaches a collection of new or existing entities to DbContext with an Unchanged state and starts tracking it. In this case, nothing will happen when we call the SaveChanges method, as the entity state is not modified.
  7. Entry: Gets an EntityEntry for the given entity. The entry provides access to change tracking information and operations for the entity.  So, using this method, we can manually set the Entity State, which DbContext will also track.
  8. Find: Find an entity with the given primary key values.
  9. FindAsync: Asynchronous method for finding an entity with the given primary key values.
  10. Remove: It sets the Deleted state to the specified entity, which will delete the data when SaveChanges() is called.
  11. RemoveRange: Sets Deleted state to a collection of entities that will delete the data in a single DB round trip when SaveChanges() is called.
  12. SaveChanges: Execute INSERT, UPDATE, or DELETE commands to the database for the entities with Added, Modified, or Deleted state.
  13. SaveChangesAsync: Asynchronous method of SaveChanges()
  14. Set: Creates a DbSet<TEntity> that can be used to query and save instances of TEntity.
  15. Update: Attaches disconnected entity with Modified state and starts tracking it. The data will be saved when SaveChagnes() is called.
  16. UpdateRange: Attaches a collection of disconnected entities with a Modified state and starts tracking it. The data will be saved when SaveChagnes() is called.
  17. OnConfiguring: Override this method to configure the database (and other options) for this context. This method is called for each instance of the context that is created.
  18. OnModelCreating: Override this method to configure further the model discovered by convention from the entity types exposed in DbSet<TEntity> properties on your derived context.
DbContext Properties in Entity Framework Core:
  1. ChangeTracker: Provides access to information and operations for entity instances this context is tracking.
  2. Database: Provides access to database-related information and operations for this context.
  3. Model: Returns the metadata about the shape of entities, the relationships between them, and how they map to the database.

Note: The DBContext is the heart of the Entity Framework Core. It is the connection between our entity classes and the database. The DBContext is responsible for database interactions like querying the database and loading the data into memory as an entity. It also tracks the changes made to the entity and persists the changes to the database.

To connect to a database, we need the database connection string. So, in the next article, I will discuss where to define the Connection String in Entity Framework Core and how to use it to interact with the SQL Server Database. In this article, I explain the need and use of the DbContext Class in Entity Framework Core. I hope you enjoy this Entity Framework Core DbContext Class article.

10 thoughts on “DbContext in Entity Framework Core”

  1. Very good article, please continue this and provide the next continuing article on where to define the connection string and how to use it in Entity Framework Core to interact with the SQL Server Database.

  2. blank

    Can you please continue on this entity framework core tutorial. This is the best tutorial i have ever found on internet.

  3. blank

    Please continue the contents of this tutorial for the EF core portion. It is the best content I have found to learn .net core. Also please add contents of Asp.Net core Web API portion.

  4. blank

    A huge thanks for all of the tutorials. Please continue with the EF Core tutorials as these are very easy to follow.

Leave a Reply

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