Aspnet Migrations
title: ASP.NET Core Migrations — Complete Guide to EF Core Database Migrations description: 'Learn EF Core migrations: add-migration, update-database, code-first schema changes, seeding data, rollbacks, and production migration strategies.' date: 2026-06-28 lastmod: 2026-06-28 weight: 23 tags: [backend, aspnet]
EF Core migrations allow evolving the database schema as the application changes, tracking modifications in C# code and generating corresponding SQL for databases.
## What You'll Learn
By the end of this tutorial, you'll create and apply migrations, manage schema changes, seed initial data, roll back problematic migrations, and deploy migrations to production safely.
## Real-World Use
A CI/CD pipeline runs `dotnet ef database update` as a release step. Each deployment applies pending migrations automatically. Failed migrations trigger rollback and alerting.
## Migrations Learning Path
```mermaid
flowchart LR
A[EF Core] --> B[Migrations]
B --> C[Auth]
C --> D[JWT]
D --> E[Web API]
B --> F{You Are Here}
style F fill:#f90,color:#fff
Setup Migrations Tools
# Install dotnet-ef tool globally
dotnet tool install --global dotnet-ef
# Verify installation
dotnet ef --version
# Install required NuGet packages
dotnet add package Microsoft.EntityFrameworkCore.Design
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
Creating Migrations
# Create initial migration
dotnet ef migrations add InitialCreate
# Add migration with description
dotnet ef migrations add AddProductTable
# Check what will be generated (script)
dotnet ef migrations script --idempotent
// Generated migration file
public partial class AddProductTable : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Products",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(type: "nvarchar(200)", maxLength: 200, nullable: false),
Price = table.Column<decimal>(type: "decimal(18,2)", precision: 18, scale: 2, nullable: false),
CategoryId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Products", x => x.Id);
table.ForeignKey(
name: "FK_Products_Categories_CategoryId",
column: x => x.CategoryId,
principalTable: "Categories",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Products_CategoryId",
table: "Products",
column: "CategoryId");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(name: "Products");
}
}
Applying Migrations
# Apply all pending migrations
dotnet ef database update
# Apply to a specific migration
dotnet ef database update AddProductTable
# Generate SQL script (safe for production)
dotnet ef migrations script -o migrate.sql
# Rollback to a previous migration
dotnet ef database update InitialCreate
Seeding Data
public class AppDbContext : DbContext
{
public static void SeedData(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Category>().HasData(
new Category { Id = 1, Name = "Electronics" },
new Category { Id = 2, Name = "Clothing" }
);
modelBuilder.Entity<Product>().HasData(
new Product { Id = 1, Name = "Laptop", Price = 999.99m, CategoryId = 1 },
new Product { Id = 2, Name = "Phone", Price = 699.99m, CategoryId = 1 }
);
}
}
// Call in OnModelCreating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
SeedData(modelBuilder);
}
// Generate migration for seed data
dotnet ef migrations add SeedCategoriesAndProducts
Production Migrations
// Program.cs - auto-migrate on startup (development only)
if (app.Environment.IsDevelopment())
{
using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Database.MigrateAsync();
}
# Production deployment script
# 1. Generate idempotent SQL script
dotnet ef migrations script --idempotent -o deploy.sql
# 2. Review and execute
sqlcmd -S production-server -d MyApp -i deploy.sql
Common Mistakes
1. Running Migrations Automatically in Production
Auto-migrate in development only. Production should use scripts reviewed by DBAs.
2. Deleting Migration Files
Never delete migration files that have been applied to any database. Create a new migration to undo changes.
3. Not Testing Down Migrations
Always verify that Down() correctly reverts changes. Rollbacks must work in emergencies.
4. Large Migration Files
Frequent small migrations are better than one massive migration. Each migration should be focused and reviewable.
5. Ignoring Seed Data Idempotency
Seed with HasData() (part of migration) rather than manual inserts. HasData checks if data exists.
Practice Questions
1. What is an EF Core migration?
A C# class that describes database schema changes. Up() applies changes, Down() reverts them.
2. How do you add a new column to an existing table?
dotnet ef migrations add AddDescriptionToProducts, then add the property to your entity class. EF detects the change.
3. How do you roll back a migration?
dotnet ef database update
4. What is an idempotent migration script?
A SQL script that checks migration state before applying. Safe to run multiple times.
5. Challenge: Create a migration that adds a Rating column to the Product table.
# Add property to Product.cs
public double? Rating { get; set; }
# Create migration
dotnet ef migrations AddRatingToProducts
# Review generated code
FAQ
Mini Project: Complete Migration Workflow
Create, apply, seed, and script migrations.
dotnet ef migrations add InitialCreate
dotnet ef database update
# Add seed data
dotnet ef migrations AddSeedData
dotnet ef migrations script -o deploy.sql
What's Next
ASP.NET Core Authentication ASP.NET Core JWT
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro