Section 3 of 7

Code-First Migrations

🎯 What You'll Learn

  • What are migrations
  • Creating migrations
  • Applying migrations
  • Updating the database
  • Rolling back migrations
  • Migration best practices

What are Migrations?

Migrations are a way to incrementally update your database schema to match your entity model while preserving existing data.

Why Use Migrations?

  • Version control: Track database schema changes
  • Team collaboration: Share schema changes via source control
  • Deployment: Apply changes to production databases
  • Rollback: Revert to previous schema versions
  • Data preservation: Update schema without losing data

Installing EF Core Tools

Install Tools Bash
# Install EF Core Tools globally
dotnet tool install --global dotnet-ef

# Or update if already installed
dotnet tool update --global dotnet-ef

# Add Design package to project
dotnet add package Microsoft.EntityFrameworkCore.Design

Creating Your First Migration

Create Initial Migration Bash
dotnet ef migrations add InitialCreate

This creates a migration file in the Migrations folder:

Migrations/20240101000000_InitialCreate.cs C#
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: 100, nullable: false),
                Price = table.Column<decimal>(type: "decimal(18,2)", nullable: false),
                Quantity = table.Column<int>(nullable: false)
            },
            constraints: table =>
            {
                table.PrimaryKey("PK_Products", x => x.Id);
            });
    }

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

Up(): Applies the migration (creates tables, columns, etc.)
Down(): Reverts the migration (drops tables, columns, etc.)

Applying Migrations

Update Database

Apply All Pending Migrations Bash
dotnet ef database update

This executes all pending migrations and creates/updates the database.

Apply at Runtime

Program.cs C#
var app = builder.Build();

// Apply migrations on startup
using (var scope = app.Services.CreateScope())
{
    var context = scope.ServiceProvider.GetRequiredService<InvenTrackDbContext>();
    context.Database.Migrate();
}

app.Run();
⚠️ Production Warning

Be careful applying migrations automatically in production. Consider using deployment scripts or manual application for better control.

Adding More Migrations

Modify Entity

Add Description Property C#
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; } = string.Empty;
    public decimal Price { get; set; }
    public string? Description { get; set; } // NEW
    public int Quantity { get; set; }
}

Create Migration

Add Migration Bash
dotnet ef migrations add AddProductDescription
Generated Migration C#
public partial class AddProductDescription : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.AddColumn<string>(
            name: "Description",
            table: "Products",
            maxLength: 500,
            nullable: true);
    }

    protected override void Down(MigrationBuilder migrationBuilder)
    {
        migrationBuilder.DropColumn(
            name: "Description",
            table: "Products");
    }
}

Apply Migration

Update Database Bash
dotnet ef database update

Common Migration Commands

Command Description
dotnet ef migrations add [Name] Create a new migration
dotnet ef database update Apply all pending migrations
dotnet ef migrations list List all migrations
dotnet ef migrations remove Remove last migration (if not applied)
dotnet ef database update [Migration] Update to specific migration
dotnet ef database update 0 Revert all migrations
dotnet ef migrations script Generate SQL script

Rolling Back Migrations

Revert to Previous Migration

Rollback Bash
# Revert to specific migration
dotnet ef database update InitialCreate

# Revert all migrations
dotnet ef database update 0

Remove Last Migration

Remove Migration (Not Applied) Bash
dotnet ef migrations remove

Generating SQL Scripts

Generate SQL Bash
# Generate script for all migrations
dotnet ef migrations script

# Generate script from specific migration
dotnet ef migrations script InitialCreate AddProductDescription

# Generate idempotent script (safe to run multiple times)
dotnet ef migrations script --idempotent

# Output to file
dotnet ef migrations script -o migration.sql

Seeding Data

Seed Data in OnModelCreating C#
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Category>().HasData(
        new Category { Id = 1, Name = "Electronics" },
        new Category { Id = 2, Name = "Furniture" },
        new Category { Id = 3, Name = "Office Supplies" }
    );

    modelBuilder.Entity<Product>().HasData(
        new Product 
        { 
            Id = 1, 
            Name = "Laptop", 
            Price = 999.99m, 
            Quantity = 10,
            CategoryId = 1
        },
        new Product 
        { 
            Id = 2, 
            Name = "Mouse", 
            Price = 29.99m, 
            Quantity = 50,
            CategoryId = 1
        }
    );
}

After adding seed data, create a migration:

Create Seed Migration Bash
dotnet ef migrations add SeedData
dotnet ef database update

Complete InvenTrack Example

Workflow Bash
# 1. Install tools
dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

# 2. Create initial migration
dotnet ef migrations add InitialCreate

# 3. Apply to database
dotnet ef database update

# 4. Make changes to entities...

# 5. Create new migration
dotnet ef migrations add AddProductDescription

# 6. Apply changes
dotnet ef database update

# 7. View migration history
dotnet ef migrations list

Best Practices

  • Descriptive names: Use clear migration names (AddProductDescription)
  • Small migrations: Create focused, single-purpose migrations
  • Review generated code: Always check migration files
  • Source control: Commit migrations to version control
  • Test migrations: Test on development database first
  • Idempotent scripts: Use for production deployments
  • Backup first: Always backup production before migrating
  • Custom SQL: Add custom SQL in migrations when needed

Key Takeaways

  • Migrations: Version control for database schema
  • dotnet ef: Command-line tool for migrations
  • Up/Down: Apply and revert migrations
  • Add migration: Create new migration from model changes
  • Update database: Apply pending migrations
  • Rollback: Revert to previous migration
  • SQL scripts: Generate for manual deployment
  • Seed data: Use HasData() for initial data
🎯 Next Steps

You now understand Code-First Migrations! In the next section, we'll explore Querying Data with LINQ—how to retrieve and filter data from your database using C# LINQ syntax.