DbContext Class in Entity Framework Core

DbContext Class in Entity Framework Core

DbContext class is the brain of Entity Framework Core and does all the communications with the database.

It allows performing the following tasks:

  • 1. Managing Database Connection.
  • 2. Configuring Entities and the Relationships between them.
  • 3. Reading, Creating, Updating & Deleting data in the database.
  • 4. Configuring change tracking.
  • 5. Caching.
  • 6. Transaction management
Example Project

Let us create an example project to understand DBContext properly. I have named my new project as DB-Context. After that I did the Installation of Entity Framework Core in it.

This application will work with a Database of a very small company. The database has just 2 table which are:

  • 1. Department – for keeping information of the different departments of the company.
  • 2. Employee – for keeping information of the different employees of the company.

For representing these 2 tables I will need to create 2 entity classes. So create 2 entity classes called Department.cs & Employee.cs inside the Models folder.

The codes of these classes are:

1. Department.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DB_Context.Models
{
    public class Department
    {
        public int Id { get; set; }
        public string Name { get; set; }

        public ICollection<Employee> Employee { get; set; }
    }
}

2. Employee.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace DB_Context.Models
{
    public class Employee
    {
        public int Id { get; set; }
        public int DepartmentId { get; set; }
        public string Name { get; set; }
        public string Designation { get; set; }

        public Department Department { get; set; }
    }
}

Now it’s time to create DbContext class.

Create DbContext class in your application

In order to use the features of DbContext class, your application context class has to derive from it.

So first create a new context class and name it CompanyContext.cs. Place this class inside the Models folder. Derive it from DbContext class of the Microsoft.EntityFrameworkCore namespace.

The CompanyContext.cs will look like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Models
{
    public class CompanyContext: DbContext
    {
    }
}

Next add the DbSet<T> for the 2 entity class which are Department and Employee.

This will make your CompanyContext class look this way:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Models
{
    public class CompanyContext: DbContext
    {
        public DbSet<Department> Department { get; set; }
        public DbSet<Employee> Employee { get; set; }
    }
}
The DbSet<T> class represents a collection for a given entity within the model and is the gateway to perform database operations against an entity.

The OnConfiguring() method

The OnConfiguring() method of the DbContext class is an override method. It allows to select and configure the data source to be used with a context. For this the DbContextOptionsBuilder class object is passed to it’s parameter.

On adding the OnConfiguring() method to the CompanyContext class it will look like:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Models
{
    public class CompanyContext : DbContext
    {
        public DbSet<Department> Department { get; set; }
        public DbSet<Employee> Employee { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(@"Server=vaio;Database=Company;Trusted_Connection=True;");
            }
        }
    }
}

Notice that I have passed the connection string to the UseSqlServer() method of the DbContextOptionsBuilder() class object.

The OnModelCreating() method

The OnModelCreating() method of the DbContext class allows configuring the model using Fluent API. This method is also an override method.

After adding it to the CompanyContext class it will look:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Models
{
    public class CompanyContext : DbContext
    {
        public DbSet<Department> Department { get; set; }
        public DbSet<Employee> Employee { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {
                optionsBuilder.UseSqlServer(@"Server=vaio;Database=Company;Trusted_Connection=True;");
            }
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Department>(entity =>
            {
                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);
            });

            modelBuilder.Entity<Employee>(entity =>
            {
                entity.Property(e => e.Designation)
                    .IsRequired()
                    .HasMaxLength(25)
                    .IsUnicode(false);

                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(100)
                    .IsUnicode(false);

                entity.HasOne(d => d.Department)
                    .WithMany(p => p.Employee)
                    .HasForeignKey(d => d.DepartmentId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Employee_Department");
            });
        }
    }
}

Inside the OnModelCreating() method I have configured both the Department and the Employee entities. As you can see, by using the IsRequired() I am making the Name property of the Department class as the required one. Similarly the HasMaxLength(100) method is used to set the maximum length of Name property of the employee entity.

Here I have only given a small introduction to FLuent API. I have covered this topic in full details at Fluent API in Entity Framework Core.

Some important methods of DbContext class are.

DbContext Methods:

Method Description
Add Adds a new entity with Added state
AddRange Adds a collection of new entities with Added state
Attach Attaches a new or existing entity with Unchanged state
AttachRange Attaches a collection of new or existing entity with Unchanged state
Remove Attaches an entity with Deleted state
RemoveRange Attaches a collection of entities with Deleted state
Update Attaches disconnected entity with Modified state
UpdateRange Attaches collection of disconnected entity with Modified state
SaveChanges Execute INSERT, UPDATE or DELETE command to the database for the entities with Added, Modified or Deleted state.

Running EF Core Migrations

It’s time to run the Migrations in order to create the database from the entity classes.

On the Package Manager Console window run these 2 commands one by one:

1. Add Migration Command

PM> dotnet ef migrations add Migration1

After this command is executed you will find a new folder called Migrations is created in your project. Check the Solution Explorer in Visual studio to find 2 .cs files inside the Migrations folder. I have shown this in the below image.

migrations folder

2. Update Migration Command

Next run the below given command which will create the database from the migration files.

PM> dotnet ef database update 

Now check the SQL server where you will find the Company database created. I have shown this in the below image.

database created by migrations
Here I have only introduced EF Core Migrations. In fact there are lots of Migration commands. I have written a complete tutorial on this topic, check it – Migrations in Entity Framework Core
Testing

Now it’s time to test if everything is working correctly or not. So let us insert a record into the database by the application and using Entity Framework core.

So create a controller called HomeController inside the Controllers folder and add the below code to it.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DB_Context.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Controllers
{
    public class HomeController : Controller
    {
        public string Index()
        {
            using (var context = new CompanyContext())
            {
                var dept = new Department()
                {
                    Name = "Designing"
                };
                context.Entry(dept).State = EntityState.Added;
                context.SaveChanges();
            }

            return "Record Interested";
        }
    }
}

Now run the project and initiate this action’s url in the browser. This will insert a new record on the Department table of the database. Open the table and you can check the newly added record. See the below image of the database table.

record inserted ef core
EF core is super easy to work with and codes are very small. Writing the same thing in ADO.NET would have required 3 times more code. I have written a complete tutorial on this thing, you should check the tutorial called Insert Records in Entity Framework Core.

Storing DB Connection String in “appsettings.json”

In the above code I have placed my database connection string in the OnConfiguring method of DBContext file. You may avoid this and would like to store the connection string in the appsettings.json file instead. Let us see how to do this.

First create appsettings.json on the project folder and add your DB connection string to it as shown below.

{
    "ConnectionStrings": {
        "DefaultConnection": "Server=vaio;Database=Company;Trusted_Connection=True;"
    }
}

Changes in DbContext

Some changes need to be done to CompanyContext class which is the DbContext for this project. These changes are:

  • Remove the Connection String from OnConfiguring method.
  • Add constructor that gets DbContextOptions object and derives from the base class.

These changes are shown below.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Models
{
    public class CompanyContext : DbContext
    {
        public CompanyContext(DbContextOptions<CompanyContext> options) : base(options)
        {
        }

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

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Department>(entity =>
            {
                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(50)
                    .IsUnicode(false);
            });

            modelBuilder.Entity<Employee>(entity =>
            {
                entity.Property(e => e.Designation)
                    .IsRequired()
                    .HasMaxLength(25)
                    .IsUnicode(false);

                entity.Property(e => e.Name)
                    .IsRequired()
                    .HasMaxLength(100)
                    .IsUnicode(false);

                entity.HasOne(d => d.Department)
                    .WithMany(p => p.Employee)
                    .HasForeignKey(d => d.DepartmentId)
                    .OnDelete(DeleteBehavior.ClientSetNull)
                    .HasConstraintName("FK_Employee_Department");
            });
        }
    }
}

Register the DbContext

Register the CompanyContext, which is the DbContext for this project, as a service in startup class. Open Startup.cs, and add the highlighted lines to the ConfigureServices method.

I have shown this by highlighting the necessary code to be added. You will also need to inject IConfiguration by Dependency Injection to the Startup.cs class constructor.

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using DB_Context.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;

namespace DB_Context
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }
        public IConfiguration Configuration { get; }

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<CompanyContext>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

            services.AddControllersWithViews();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            // ...
        }
    }
}
Testing

Now to perform EF core operations you have to inject the DbContext (here it is CompanyContext) in the controller through the Dependency Injection Feature of ASP.NET Core, and then use it to perform your db operations.

Check the below Entity Framework Code code where I am performing the Record Insertion into the database.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using DB_Context.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;

namespace DB_Context.Controllers
{
    public class HomeController : Controller
    {
        private CompanyContext context;
        public HomeController(CompanyContext cc)
        {
            context = cc;
        }

        public string Index()
        {
            var dept = new Department()
            {
                Name = "Coding"
            };
            context.Entry(dept).State = EntityState.Added;
            context.SaveChanges();

            return "Record Interested";
        }
    }
}

You can download the source code from the below link.

DOWNLOAD

Share this article -

yogihosting

ABOUT THE AUTHOR

This article has been written by the Technical Staff of YogiHosting. Check out other articles on "ASP.NET Core, jQuery, EF Core, SEO, jQuery, HTML" and more.