Pebellslearn by building
0%
RoadmapsMatrixCoursesSandboxSign in
Object Relational Mapping  ›  Lesson

Code First and Migrations — The Schema Follows Your Classes

Code First + Migrations 14 minIn code-first development the C# model is the source of truth, and each migration is a versioned, reversible step that brings the database schema in line with it.

Code First and Migrations — The Schema Follows Your Classes

ReadingRoom's Book class needs an ISBN. You could log into the database and add a column by hand — then do it again on the test server, and again in production, and hope nobody forgets. Code first reverses the direction: you change the C# class, and EF Core generates a versioned script that changes every database the same way.

The rule

Change the class, add a migration, update the database.

Migrations need the EF tools once per machine and the design package once per project:

dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

Then the loop is always the same:

dotnet ef migrations add AddBookIsbn   # compare model to snapshot, write a migration
dotnet ef database update              # apply pending migrations to the database

A migration is a C# class with two methods:

public partial class AddBookIsbn : Migration
{
    protected override void Up(MigrationBuilder mb) =>
        mb.AddColumn<string>(name: "Isbn", table: "Books", nullable: true);

    protected override void Down(MigrationBuilder mb) =>
        mb.DropColumn(name: "Isbn", table: "Books");
}

Up moves the schema forward; Down undoes it. EF records every applied migration in a table called __EFMigrationsHistory, so each database knows exactly which steps it has had. A model snapshot file in the project remembers the last known model, which is how the next migrations add works out what changed.

Useful extras: dotnet ef migrations remove deletes the last migration if it has not been applied; dotnet ef migrations script produces plain SQL you can review and run in a deployment.

Rules like maximum lengths and relationships come from attributes ([MaxLength(20)]) or from OnModelCreating in the DbContext, and they flow into migrations too.

The shortcut

Treat migrations like commits for your schema: one small, named migration per model change, committed to Git with the code that needs it.

Shipping the ISBN columnStep 1 of 4
  1. Change the model

    Add public string? Isbn { get; set; } to Book.

The trap: renaming a property and trusting the migration blindly. EF may generate "drop column, add column", which deletes the data. Read every migration before applying it.

Drills

Answer fast — trust the rule.

quick drill

You changed an entity class. What comes next?

quick drill

What does a migration's Down method do?

quick drill

How does a database know which migrations it already has?

quick drill

Why read a generated migration before applying it?

Remember

  • Change the class, add a migration, update the database.
  • One small, named migration per change, committed with the code.
  • Read every migration; renames can become drop-and-add.

Practice — level up

0/1 solved

Write your answer, then compare it with a rubric and a model answer.

ExplainAdding a column safely

You add public string? Isbn { get; set; } to ReadingRoom's Book class. Explain the commands that get this into your local database and later into production, what the generated migration contains, and why you should not edit the database by hand instead.