EF Core, DBOs, and migrationsMigrations: generate, don't hand-roll
No narration yet
Module 10 · Lesson 213 min

Migrations: generate, don't hand-roll

You change the schema by changing the DBO model and then running the EF CLI to generate a migration. You do not hand-write the migration. This is the highest-severity rule in the anti-pattern list (#4, severity 10) because hand-rolled and wrongly-removed migrations produce a snapshot that diverges from the real schema, and that divergence is a production incident.

A generated migration (real AddRevokedAtUtc)
public partial class AddRevokedAtUtcToFlightDisruptionCostCalc : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder) =>
        migrationBuilder.AddColumn<DateTime>(
            name: "revoked_at_utc",
            table: "flight_disruption_cost_calcs",
            type: "timestamptz",
            nullable: true);

    protected override void Down(MigrationBuilder migrationBuilder) =>
        migrationBuilder.DropColumn(name: "revoked_at_utc", table: "flight_disruption_cost_calcs");
}
The migration workflow (CLI only)
# 1. change the DBO model in code
# 2. generate the migration from the model diff
dotnet ef migrations add AddRevokedAtUtcToFlightDisruptionCostCalc
# 3. READ the generated Up/Down before committing
# 4. verify it applies on a fresh DB
dotnet ef database update
Practice

Try it yourself

Check

Read a generated migration

Confirm what a real, CLI-generated migration looks like so you can tell it from a hand-rolled one.

You should see

A file under persistence/Migrations/ with a timestamp prefix, #nullable disable, and Up/Down methods calling migrationBuilder.AddColumn/DropColumn with snake_case table and column names. It reads as generated: no bespoke SQL, no migrationBuilder.Sql(...), symmetric Up/Down.

Quiz

Changing an unshipped table

A table you added last week is behind a feature flag that's still OFF in test and prod. You now need to change its primary key type. What do you do?