| name | migration-workflow |
| description | Safe migration workflows for EF Core database migrations, .NET version upgrades, and NuGet dependency updates. Includes rollback strategies and verification steps. Load when: "migration", "add migration", "ef migration", "update database", "upgrade nuget", "update packages", "dependency update", "version upgrade".
|
Migration Workflow
Core Principles
- Verify before applying — Always review generated migration SQL before applying to any database.
dotnet ef migrations script shows the exact SQL. Never apply blindly.
- Rollback plan always — Every migration has a rollback. For EF Core:
dotnet ef database update <PreviousMigration>. For packages: git revert. For .NET version: branch-based rollback. Document the rollback before applying.
- Test after migration — Run the full test suite after every migration step. Migrations that break tests are not complete. Integration tests with Testcontainers catch real database issues.
- One change per migration — Each EF Core migration should represent a single logical change (add table, rename column, add index). Multiple unrelated changes in one migration make rollback impossible.
- Incremental updates — Update one package at a time, build, test. Update one target framework at a time, build, test. Never batch unrelated changes — when something breaks, you need to know which change caused it.
Patterns
EF Core Migration Workflow
Step-by-step workflow for creating and applying database migrations safely.
Step 1: Check Current State
dotnet ef migrations list --project src/Infrastructure --startup-project src/Api
dotnet ef database update --project src/Infrastructure --startup-project src/Api -- --dry-run
Step 2: Create Migration
Use descriptive names that explain the change, not the entity:
dotnet ef migrations add AddOrderShippingAddress --project src/Infrastructure --startup-project src/Api
dotnet ef migrations add RenameCustomerEmailToContactEmail --project src/Infrastructure --startup-project src/Api
dotnet ef migrations add AddIndexOnOrderCreatedAt --project src/Infrastructure --startup-project src/Api
dotnet ef migrations add Order
dotnet ef migrations add UpdateCustomer
Step 3: Review Generated SQL
dotnet ef migrations script --idempotent --project src/Infrastructure --startup-project src/Api
dotnet ef migrations script PreviousMigration AddOrderShippingAddress --project src/Infrastructure --startup-project src/Api
Check for:
- ⚠️ Data loss:
DROP COLUMN, DROP TABLE, column type changes that lose precision
- ⚠️ Long locks:
ALTER TABLE on large tables without concurrent index creation
- ⚠️ Default values: New non-nullable columns need defaults for existing rows
Step 4: Handle Data Loss Warnings
If EF Core warns about potential data loss:
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<string>("ContactEmail", "Customers", nullable: true);
migrationBuilder.Sql("UPDATE \"Customers\" SET \"ContactEmail\" = \"Email\"");
migrationBuilder.AlterColumn<string>("ContactEmail", "Customers", nullable: false);
migrationBuilder.DropColumn("Email", "Customers");
}
Step 5: Apply and Verify
dotnet ef database update --project src/Infrastructure --startup-project src/Api
dotnet test
Step 6: Rollback (if needed)
dotnet ef database update PreviousMigrationName --project src/Infrastructure --startup-project src/Api
dotnet ef migrations remove --project src/Infrastructure --startup-project src/Api
NuGet Dependency Update Workflow
Safe process for updating NuGet packages without breaking the build.
Step 1: Audit Current State
dotnet list package --outdated
dotnet list package --vulnerable
Step 2: Categorize Updates
- Patch updates (1.0.0 → 1.0.1): Safe, bug fixes only. Update all patches at once.
- Minor updates (1.0.0 → 1.1.0): Usually safe, new features. Update one at a time.
- Major updates (1.0.0 → 2.0.0): Breaking changes expected. Update one at a time, read release notes.
Step 3: Update Incrementally
dotnet outdated --upgrade Patch
dotnet add src/Api/Api.csproj package Serilog.AspNetCore --version 9.1.0
dotnet build
dotnet test
dotnet add src/Api/Api.csproj package WolverineFx
dotnet build
dotnet test
Step 4: Reference Package Recommendations
Check knowledge/package-recommendations.md before adding new packages:
- Is there a built-in .NET alternative? (e.g., HybridCache vs third-party cache)
- Is the package actively maintained?
- Does it align with kit recommendations?
Step 5: Verify
dotnet build
dotnet test
.NET Version Migration Workflow
Structured upgrade from older .NET versions to .NET 10.
Step 1: Assess Current State
→ get_project_graph
List all projects and their target frameworks.
Flag: mixed TFMs, test projects on different versions.
Step 2: Pre-Migration Checklist
Step 3: Update global.json
{
"sdk": {
"version": "10.0.100",
"rollForward": "latestMinor"
}
}
Step 4: Update Target Frameworks
Update each .csproj (or Directory.Build.props if centralized):
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<LangVersion>14</LangVersion>
</PropertyGroup>
Step 5: Update Packages
dotnet outdated --upgrade Major --include Microsoft.*
dotnet build
Step 6: Adopt New Features
Reference knowledge/dotnet-whats-new.md:
- Replace
DateTime.Now/DateTime.UtcNow with TimeProvider
- Use
HybridCache instead of IDistributedCache
- Convert classes to primary constructors where appropriate
- Use collection expressions:
int[] x = [1, 2, 3]
- Use the
field keyword in property accessors
Step 7: Verify
dotnet build
dotnet test
dotnet format --verify-no-changes
Then run the health check workflow from the project-setup skill to establish the new baseline.
Anti-patterns
Applying Migrations Without Reviewing SQL
dotnet ef database update
dotnet ef migrations script --idempotent > review.sql
dotnet ef database update
Updating All Packages at Once
dotnet outdated --upgrade Major
dotnet build
dotnet add package WolverineFx
dotnet build && dotnet test
dotnet add package Serilog --version 5.0.0
dotnet build && dotnet test
Skipping Tests After Migration
dotnet ef database update
dotnet ef database update
dotnet test
Multiple Unrelated Changes in One Migration
dotnet ef migrations add UpdateEverything
dotnet ef migrations add AddShippingAddressTable
dotnet ef migrations add RenameCustomerEmailColumn
dotnet ef migrations add DropUnusedOrderIndex
Decision Guide
| Scenario | Workflow | Key Step |
|---|
| New database table | EF Core Migration | Create entity + config + migration |
| Column rename | EF Core Migration | Review SQL for data preservation |
| Add index | EF Core Migration | Check for long locks on large tables |
| Data transformation | EF Core Migration + raw SQL | Custom Up() with SQL statements |
| Outdated packages | NuGet Update | One at a time, build + test between each |
| Vulnerable package | NuGet Update (urgent) | Update immediately, test, deploy |
| .NET version upgrade | .NET Migration | Phase 1-4, verify at each phase |
| Add new package | NuGet Update | Check package-recommendations.md first |
ExecuteUpdateAsync vs migration | Depends | Migration for schema; ExecuteUpdateAsync for bulk data updates at runtime |
| Modify existing migration | Never if already applied | Create new migration instead |