Skip to main content

Migrations

Level: Beginner

ℹ️ Where This Fits

Migrations track schema changes over time. This enables version control of your database, enabling teams to collaborate and deploy safely.

ℹ️ What You'll Learn
  • Migration purpose: Track database schema changes as code (version control friendly)
  • Workflow: Modify entity → add migration → review SQL → update database
  • dotnet ef migrations add: Create new migration file based on model changes
  • dotnet ef database update: Apply pending migrations to database
  • Automatic timestamping: Migration files timestamped (202401151430_AddStudentTable.cs)
  • Up method: SQL to apply migration (ALTER TABLE, CREATE TABLE, etc)
  • Down method: SQL to revert migration (rollback)
  • Migration history: __EFMigrationsHistory table tracks applied migrations
  • Idempotent scripts: Migrations check if already applied (safe to re-run)
  • Removing migrations: dotnet ef migrations remove (only before applying)
  • Script-only: dotnet ef migrations script (generates SQL without applying)
  • School Management migrations: Initial, AddStudentTable, AddExamResults, AddFeePayments
  • Common mistakes: Modifying migration files manually, removing applied migrations, losing down methods

Basic Migration Workflow

# 1. Create migration (generates SQL based on model changes)
dotnet ef migrations add InitialCreate

# 2. Apply migration to database
dotnet ef database update

# 3. View generated SQL (without applying)
dotnet ef migrations script

Migration File Example

Generated file: Migrations/20240115143045_InitialCreate.cs

public partial class InitialCreate : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Students",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
Name = table.Column<string>(maxLength: 100, nullable: false),
ClassName = table.Column<string>(maxLength: 10, nullable: false),
RollNumber = table.Column<string>(maxLength: 20, nullable: false),
DateOfBirth = table.Column<DateTime>(nullable: false),
Status = table.Column<int>(nullable: false),
CreatedAt = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Students", x => x.Id);
});
}

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

Adding Foreign Key Migration

dotnet ef migrations add AddExamToStudent

Generated SQL:

protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Exams",
columns: table => new
{
Id = table.Column<int>(nullable: false)
.Annotation("SqlServer:Identity", "1, 1"),
ExamName = table.Column<string>(maxLength: 100, nullable: false),
SubjectId = table.Column<int>(nullable: false),
ExamDate = table.Column<DateTime>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Exams", x => x.Id);
table.ForeignKey(
name: "FK_Exams_Subjects_SubjectId",
column: x => x.SubjectId,
principalTable: "Subjects",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
});
}

Updating Existing Migration (Before Apply)

If migration not yet applied:

# Remove the migration (before update)
dotnet ef migrations remove

# Modify your entities

# Create new migration
dotnet ef migrations add FixedMigrationName

# Apply
dotnet ef database update

Reverting Applied Migrations

Revert to previous migration:

# List migrations
dotnet ef migrations list

# Revert to specific migration (this runs Down method)
dotnet ef database update PreviousMigration

Generate SQL Script (Without Applying)

# Generate SQL to file
dotnet ef migrations script > migrations.sql

# Generate SQL from specific migration range
dotnet ef migrations script AddStudents AddFees > fee-migrations.sql

Best Practices

✓ Always review generated migrations before applying ✓ Never modify applied migrations (create new one instead) ✓ Use descriptive migration names ✓ Commit migrations to git ✓ Apply migrations in order

💡 Safe Schema Changes

For production:

  1. Run migration in staging first
  2. Review generated SQL
  3. Backup database before applying
  4. Apply with rollback plan ready
🤖Use AI to Learn Faster

Use ChatGPT, Claude, or Copilot to go deeper on Migrations. Try these prompts:

  • "What's the difference between 'add migration' and 'update database'?"
  • "How do you revert a migration that was already applied?"
  • "Why should you review the generated SQL before applying?"
  • "What's stored in the __EFMigrationsHistory table?"

💡 Tip: After reading this article, paste your own code into AI and ask "What could go wrong here and why?" — fastest way to find edge cases and deepen understanding.

Next Article

-> 05. LINQ & Querying

nexcoding.in