Mert Özen Further With Every Line
Backend .NET Core Web API — #09

Introduction to Entity Framework Core: DbContext and Your First Migration

Mert Özen Aug 2, 2026 13 min 78 views
Introduction to Entity Framework Core: DbContext and Your First Migration

We start storing our data in a real database. What EF Core is, what DbContext represents, how tables are defined with DbSet, and how the database is created with the first migration, step by step.

Until now we've always cheated. Our users lived in memory, inside a fixed array; every time we closed the application, they all vanished. This was fine for learning, but a real application doesn't work this way. The data needs to be persistent, that is, stored in a database. Today we meet Entity Framework Core and write our data to a real database for the first time.

What Is Entity Framework Core?

Entity Framework Core, EF Core for short, is the most widely used ORM in the .NET world. ORM means "Object-Relational Mapping." It sounds complex, but its job is actually very clear: it builds a bridge between your C# objects and the tables in the database.

Without this bridge, you'd have to write SQL queries by hand to talk to the database. SELECT to fetch a user, INSERT to add one... EF Core takes this burden off you. You write familiar C# code like users.Add(user), and EF Core translates it into the appropriate SQL in the background and sends it to the database. So you keep thinking in objects, and it does the translation into the database language. Like an interpreter between two sides speaking two different languages.

Let's Add the Packages First

EF Core doesn't come ready inside .NET; you need to add it to your project separately. To keep the examples simple in this series, we'll use SQLite; a file-based database that requires no setup and is ideal for learning. Open the terminal in the project folder and add these two packages:

dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design

The first package is the provider needed to work with SQLite; the second is needed for the migration commands we'll use shortly. Once the installation is done, you're ready to use EF Core.

DbContext: The Door to the Database

The heart of EF Core is the DbContext class. Think of it as the single door between your application and the database. Every database-related operation passes through this door: reading, adding, updating, deleting data. We create our own context class by deriving it from EF Core's DbContext class:

using Microsoft.EntityFrameworkCore;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions options)
        : base(options)
    {
    }

    public DbSet Users { get; set; }
}

There are two important things in this tiny class. The constructor takes DbContextOptions; this carries the settings for which database to connect to and how, and we'll provide these settings in Program.cs shortly. The one that really stands out is the DbSet<User> Users line.

DbSet: The Representative of a Table

DbSet<User> represents a table in the database. This line tells EF Core: "There will be a Users table in the database that holds User objects." Each DbSet corresponds to a table. Later, if you add products you'll write DbSet<Product> Products, and if you add orders, DbSet<Order> Orders.

You can think of it like an Excel file: the DbContext is the whole file, and each DbSet is a separate sheet in that file. When you write context.Users in your code, it means you're actually accessing that entire table; from there you can query, add new rows, and update existing ones.

Introducing DbContext to Program.cs

We wrote the context class, but EF Core needs to recognize it and know which database to connect to. We do this in the service registration phase you know from the second article, that is, before builder.Build():

builder.Services.AddDbContext(options =>
    options.UseSqlite("Data Source=app.db"));

This line does two jobs. With AddDbContext it registers our context to the system, and with UseSqlite it says which database we'll use. "Data Source=app.db" is the connection string; here we specify that a SQLite file named app.db in the application's working folder will be used. In real projects, instead of writing this connection string directly in the code, we keep it in the appsettings file; we'll touch on that in the configuration article.

Migration: What Is It, Why Is It Needed?

Our classes are ready, but there's no database yet. This is exactly where migration comes in. A migration is a plan that takes the structure in your C# classes and turns it into concrete steps to be applied to the database. It produces instructions like "create this table, add these columns" on your behalf.

Think of a migration like version control for the database. When you make a change on the code side (for example, adding a new field to your entity), you create a new migration, and EF Core knows how to reflect this change to the database. This way, the database's structure always stays in sync with your code, and you can track this history step by step.

Creating and Applying the First Migration

To manage migrations, we need EF Core's command-line tool. Installing it once is enough:

dotnet tool install --global dotnet-ef

Now we create our first migration. We give it a meaningful name; since it's the initial setup, "InitialCreate" is a suitable name:

dotnet ef migrations add InitialCreate

This command creates a folder named Migrations in your project and places code files inside it that describe how to create the Users table. But note: this step hasn't touched the database yet, it only prepared the plan. To actually apply the plan, that is, to create the database, we run this command:

dotnet ef database update

When this command runs, a SQLite file named app.db appears in the project folder, and your Users table is created inside it. Now you have a real, persistent database. Even if you close and reopen the application, the data will stay in place.

A Small Experiment

Apply the steps above from start to finish in your own project: add the packages, write the AppDbContext, register it in Program.cs, then create the migration and update the database. See the app.db file that appears in your folder. If you like, open this file with a free SQLite viewer and examine the columns of the Users table; seeing with your own eyes that each property in your entity turned into a column makes it very clear what EF Core does. There's no data in the table yet, but the structure is ready.

In the next article we start actually using this database: we'll read and write data through the DbContext from our controller, and discuss what the service layer is for and the question "is the repository pattern really necessary?" The foundation you set up today is the ground everything else will sit on.