Home About Skills Products Work
Projects Services Experience
Learn
Tutorials Courses Blogs Resources
Contact
Blog · .NET

Entity Framework Core Migrations: A Practical Guide

Entity Framework Core migrations let you evolve your database schema through version-controlled C# code instead of manually editing tables — the .NET equivalent of Laravel's migration system, with its own specific workflow worth understanding properly.

Creating Your First Migration

dotnet ef migrations add CreatePostsTable

EF Core compares your current DbContext model classes against the last known database snapshot and generates a migration file describing exactly what changed:

public partial class CreatePostsTable : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.CreateTable(
            name: "Posts",
            columns: table => new
            {
                Id = table.Column<int>(nullable: false)
                    .Annotation("Sqlite:Autoincrement", true),
                Title = table.Column<string>(maxLength: 255, nullable: false),
                CreatedAt = table.Column<DateTime>(nullable: false),
            },
            constraints: table => table.PrimaryKey("PK_Posts", x => x.Id));
    }

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

The Down method is what makes a migration reversible — always verify EF Core generated a correct one, especially for anything beyond a simple add/drop column.

Applying Migrations

dotnet ef database update

This runs any migrations not yet applied to the target database, in order, tracked in a __EFMigrationsHistory table — the same role Laravel's migrations table plays.

Changing an Existing Column

public class Post
{
    public int Id { get; set; }
    [MaxLength(500)] // was 255
    public string Title { get; set; }
}
dotnet ef migrations add IncreaseTitleLength
dotnet ef database update

Change the model class first, then generate the migration — EF Core diffs the model against the database, not the other way around.

Seeding Data

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Category>().HasData(
        new Category { Id = 1, Name = "General" },
        new Category { Id = 2, Name = "Tutorials" }
    );
}

Data configured via HasData becomes part of the migration itself — it runs exactly once, tracked the same way schema changes are, rather than needing a separate seeding script run manually.

Rolling Back Safely

dotnet ef database update PreviousMigrationName

Rolling back in production should always be tested against a staging copy first — a migration that DROPPED a column can't un-drop the data that was in it, regardless of how correct the Down method looks on paper.

Building Your First REST API with ASP.NET Core

Building Your First REST API with ASP.NET Core

Minimal APIs, Entity Framework Core, and FluentValidation — a real, working ASP.NET Core API without controller-class ceremony.

ASP.NET Core Web API Authentication with JWT

ASP.NET Core Web API Authentication with JWT

A complete JWT authentication setup for ASP.NET Core — issuing tokens, protecting endpoints, and role-based authorization.

Clean Architecture in ASP.NET Core

Clean Architecture in ASP.NET Core

Structuring an ASP.NET Core app so business logic has zero dependency on frameworks or databases — Domain, Application, Infrastructure, and Web layers.

Esc