0Pricing
C# Academy · Lesson

Migrations & Schema Management

Create, apply, and roll back migrations to evolve your database schema safely.

Migrations & Schema Management is a free C# Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C# Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

What Are EF Core Migrations?

Migrations are code-generated files that describe incremental database schema changes. Instead of writing DDL SQL by hand, EF Core generates and applies it automatically, keeping code and database in sync.

Installing EF Core Tools

The EF Core CLI tool (dotnet-ef) must be installed globally (or as a local tool) to run migration commands from the terminal.

# Install globally
dotnet tool install --global dotnet-ef

# Verify
dotnet ef --version

# Required NuGet packages in your project:
# Microsoft.EntityFrameworkCore.Design
# Microsoft.EntityFrameworkCore.SqlServer (or Sqlite, etc.)

Creating Your First Migration

dotnet ef migrations add compares your current model to the last snapshot and generates a migration file with Up() (apply) and Down() (rollback) methods.

# Create initial migration
dotnet ef migrations add InitialCreate

# Output files created:
# Migrations/20240101_InitialCreate.cs       <- Up/Down
# Migrations/20240101_InitialCreate.Designer.cs
# Migrations/AppDbContextModelSnapshot.cs   <- current model

Inside a Migration File

Each migration has an Up method (applies changes) and a Down method (reverts them). EF Core generates these automatically from model differences.

public partial class InitialCreate : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Products",
            columns: table => new
            {
                Id    = table.Column<int>(nullable: false)
                             .Annotation("SqlServer:Identity", "1, 1"),
                Name  = table.Column<string>(maxLength: 200, nullable: false),
                Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false)
            },
            constraints: table => table.PrimaryKey("PK_Products", x => x.Id));
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropTable(name: "Products");
    }
}

Applying Migrations

dotnet ef database update applies all pending migrations. EF Core tracks which migrations have run in the __EFMigrationsHistory table.

# Apply all pending migrations
dotnet ef database update

# Apply up to a specific migration
dotnet ef database update AddProductIndex

# Roll back to a previous migration
dotnet ef database update InitialCreate

Programmatic Migration at Startup

In production you can apply migrations programmatically on startup so the database is always up to date without manual CLI steps.

var app = builder.Build();

// Apply pending migrations at startup
using (var scope = app.Services.CreateScope())
{
    var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
    await db.Database.MigrateAsync();
}

app.Run();

Adding a Column in a New Migration

Add a property to your entity, then create a new migration. EF Core detects the change and generates an AddColumn operation.

// 1. Add property to entity
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = "";
    public decimal Price { get; set; }
    public string? Description { get; set; } // NEW
}

// 2. Generate migration
// dotnet ef migrations add AddProductDescription

// Generated Up():
migrationBuilder.AddColumn<string>(
    name: "Description",
    table: "Products",
    nullable: true);

Data Seeding in Migrations

Use HasData in OnModelCreating to seed reference data. EF Core includes it in migration Up as INSERT statements.

modelBuilder.Entity<Category>().HasData(
    new Category { Id = 1, Name = "Electronics" },
    new Category { Id = 2, Name = "Books" },
    new Category { Id = 3, Name = "Clothing" }
);

// Then regenerate the migration:
// dotnet ef migrations add SeedCategories

Custom SQL in Migrations

When you need DDL that EF Core can't generate automatically (triggers, views, stored procedures), use migrationBuilder.Sql().

protected override void Up(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql(@"
        CREATE VIEW vw_ActiveProducts AS
        SELECT Id, Name, Price
        FROM Products
        WHERE IsActive = 1
    ");
}

protected override void Down(MigrationBuilder migrationBuilder)
{
    migrationBuilder.Sql("DROP VIEW vw_ActiveProducts");
}

Removing a Migration

If you haven't applied a migration yet, you can delete it with dotnet ef migrations remove. Only the last migration can be removed this way.

# Remove the last unapplied migration
dotnet ef migrations remove

# List all migrations and their status
dotnet ef migrations list

# Script all migrations to SQL (for DBA review)
dotnet ef migrations script --output deploy.sql

Real-World: CI/CD Migration Strategy

In a CI/CD pipeline, generate a migration script and let a DBA review it before applying to production — never run MigrateAsync() blindly in critical production systems.

# Generate idempotent script for all pending migrations
dotnet ef migrations script --idempotent --output migrations.sql

# Review migrations.sql, then apply via sqlcmd / psql:
# sqlcmd -S server -d db -i migrations.sql

Quick Check

Which EF Core table tracks which migrations have already been applied to a database?

Recap: Migrations & Schema Management

Key takeaways:

  • dotnet ef migrations add <Name> generates incremental schema change files
  • Each migration has Up() (apply) and Down() (rollback) methods
  • dotnet ef database update applies pending migrations
  • Use MigrateAsync() in app startup for automated deployments
  • Generate idempotent SQL scripts for DBA review in production pipelines

Frequently asked questions

Is the “Migrations & Schema Management” lesson free?

Yes — the full text of “Migrations & Schema Management” is free to read here on the web, and the C# Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C# Academy course, upgrade to CoddyKit PRO.

What will I learn in “Migrations & Schema Management”?

Create, apply, and roll back migrations to evolve your database schema safely. You practise C# Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C# Academy?

No prior experience is required. C# Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Migrations & Schema Management” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C# Academy lesson?

Yes. Every C# Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. DbContext & DbSet Basics
  2. Migrations & Schema Management
  3. CRUD Operations with EF Core
  4. Relationships: One-to-Many & Many-to-Many
← Back to C# Academy