entity-framework-configuracion-dbcontext

What is DbContext and how to use it in Entity Framework

  • 4 min

In this tutorial, we will explore the DBContext, object, which represents the core component of Entity Framework and acts as a bridge between our .NET application and the underlying database.

The DBContext is the main class that allows us to interact with the database without writing SQL directly, providing methods to perform data read, write, update, and delete operations.

Main Features

  • Allows defining the data model through DbSet<T> properties
  • Manages connections with the database
  • Allows performing queries to the database using LINQ
  • Provides methods to manage the lifecycle of entities

In other words, it is the most important class and the core of Entity Framework, as it is the one that allows us to interact with the database without the need to write SQL manually.

Basic Configuration of DbContext

To use the DbContext class, we typically create a class that inherits from it, in which we define which tables (entities) will be associated with our database.

Within our DbContext class (which inherits from it)

  • We will define properties of type DbSet<T>, which represent tables in the database.
  • Each DbSet<T> allows interaction with the associated table, where T is the entity type (for example, User or Product).

Let’s see it with an example,

using Microsoft.EntityFrameworkCore;

public class MyContext : DbContext
{
    // Represents the "Products" table in the database
    public DbSet<Product> Products { get; set; }

    // Represents the "Customers" table in the database
    public DbSet<Customer> Customers { get; set; }
}
Copied!

In this example,

  • We have created a class named MyContext that inherits from DbContext
  • Inside this class, we have defined two DbSet properties: Products and Customers
    • These properties represent the database tables.

Configuring the Database Connection

The DbContext needs to know how to connect to the database. We have several ways to pass the configuration to it,

In applications where we do not have a dependency injection service (typically console or desktop applications) we can use the OnConfiguring method to set up the configuration

public class MyContext : DbContext
{
    public DbSet<Product> Products { get; set; }
    public DbSet<Customer> Customers { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
	    const string connectionString = Configuration.GetConnectionString("DefaultConnection");

        // Configures the connection to SQL Server
        optionsBuilder.UseSqlServer(connectionString);
    }
}
Copied!

In this example, we have overridden the OnConfiguring method to specify the connection string to SQL Server.

In ASP.NET Core applications, it is common and recommended to use dependency injection to configure the DbContext.

We typically configure this in the application’s Program.cs file, using the AddDbContext method of the service container,

const string connectionString = Configuration.GetConnectionString("DefaultConnection");

// Configures the DbContext to use SQL Server
services.AddDbContext<MyContext>(options =>
    options.UseSqlServer(connectionString)
);
Copied!

In some applications, the dependency injection scope does not match the desired lifetime of the DbContext (for example, in Blazor, where the connection is persistent, not per request).

In this case, we can register a factory, which can create new DbContext instances on demand,

services.AddDbContextFactory<MyContext>(options => 
    options.UseSqlServer(connectionString);
Copied!

Afterwards, services using the factory could create a new DbContext by doing

MyContext context = _contextFactory.CreateDbContext()
Copied!

Proper Lifecycle Usage

The DbContext should have a limited lifecycle. It is normally configured as Scoped in the DI container, ensuring one instance is created per HTTP request.

Common Operations with DbContext

Now that we have configured our DbContext and defined the classes with DbSet, we can already perform operations with it.

For example, let’s look at some basic CRUD operations (Create Read Update and Delete)

The Add or AddRange method is used to insert new entities into the database:

var newUser = new User { Name = "Luis Llamas", Email = "[email protected]" };
_context.Users.Add(newUser);
await _context.SaveChangesAsync();
Copied!

Queries are performed using LINQ:

var user = await _context.Users
    .FirstOrDefaultAsync(u => u.Email == "[email protected]");
Copied!

Modify data in memory and save the changes:

var user = await _context.Users.FindAsync(1);
if (user != null)
{
    user.Name = "Luis Updated";
    await _context.SaveChangesAsync();
}
Copied!

Delete entities using Remove:

var user = await _context.Users.FindAsync(1);
if (user != null)
{
    _context.Users.Remove(user);
    await _context.SaveChangesAsync();
}
Copied!

Isn’t it easy? But there’s much more! We will explore all these elements in depth in the upcoming tutorials.