EF Core Migration Standards · EF-04
Migrations must be named descriptively and consistently · EF-04.1 · MUST
The name of each migration must be a clear indication of what a migration does, before opening the file. Always use PascalCase verb-noun names which describe the change(s) introduced in the migration.
Good Example: Descriptive migration names
20260521093000_AddColumnIsbnToBook.cs
20260521094500_CreateAuthorTable.cs
20260521100000_AddIndexOnOrderCreatedDate.cs
20260521340000_CreateStripePaymentConfigurationTable.csBad Example: Vague or inconsistent migration names
20260521093000_AddData.cs
20260521094500_TC_changes.cs
20260521100000_Fix_bug_584223.csNever edit a migration once it has been applied to a shared environment · EF-04.2 · MUST
Never edit existing migrations once they have already been applied to a deployed database. After the migration is applied it is recorded in the __EFMigrationsHistory table, and will never be reapplied.
Good Example: Fix forward with a new migration
# Original migration AddBookIsbnColumn has already been deployed.
# The Isbn column needs a longer max length.
dotnet ef migrations add IncreaseBookIsbnLengthBad Example: Editing an applied migration
// Editing AddBookIsbnColumn.cs after it has already been applied
// to staging. The change will never run again on environments
// where the migration is already recorded as applied.
migrationBuilder.AddColumn(
name: "Isbn",
table: "Books",
type: "nvarchar(20)", // was nvarchar(13)
nullable: false);Keep migrations reversible · EF-04.3 · MUST
Every migration must define both Up and Down methods such that all changes can be rolled back when needed. Any operation in Up which cannot be expressed in Down is heavily discouraged.
Good Example: Reversible migration
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn(
name: "Isbn",
table: "Books",
type: "nvarchar(13)",
nullable: false,
defaultValue: "");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "Isbn",
table: "Books");
}Bad Example: Non-reversible migration
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("ALTER TABLE Books ADD Isbn nvarchar(13) NOT NULL DEFAULT '';");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}Keep migrations idempotent · EF-04.4 · MUST
Every migration must be able to be safely reapplied multiple times without adverse effects.
Note: This usually only applies to raw SQL inside migrations. Most MigrationBuilder commands are intrinsically guarded.
Good Example: Guarded raw SQL
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql(@"
IF NOT EXISTS (SELECT 1 FROM [Genres] WHERE [Name] = N'Fiction')
INSERT INTO [Genres] ([Name]) VALUES (N'Fiction');
");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.Sql("DELETE FROM [Genres] WHERE [Name] = N'Fiction';");
}Bad Example: Unguarded insert (clones data on every run)
protected override void Up(MigrationBuilder migrationBuilder)
{
// Re-running inserts another 'Fiction' row each time — duplicates accumulate.
migrationBuilder.Sql("INSERT INTO [Genres] ([Name]) VALUES (N'Fiction');");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
}Each migration should contain one logical change · EF-04.5 · SHOULD
Every migration must be able to be reviewed, applied and rolled back on its own. Changes cannot be reverted independently when they are contained within a migration responsible for executing other, unrelated changes.
Good Example: One change per migration
dotnet ef migrations add AddBookIsbnColumn
dotnet ef migrations add AddIndexOnOrderCreatedDate
dotnet ef migrations add RenameAuthorBioToDescriptionBad Example: Multiple unrelated changes in one migration
// Migration: MiscChanges
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn(name: "Isbn", table: "Books", /* ... */);
migrationBuilder.CreateIndex(name: "IX_Orders_CreatedDate", table: "Orders", /* ... */);
migrationBuilder.RenameColumn(name: "Bio", table: "Authors", newName: "Description");
}