dotnet-migrate

Installation
SKILL.md

Safe migration workflow (.NET)

Migrations are where a working codebase quietly acquires risk: a column drop that loses data, a framework bump that breaks at runtime not compile time, a transitive package that shifts behavior under you. The defense is the same four rules in every flow below.

  • Preview before you apply. Read the generated SQL, the breaking-change list, the changelog - never run a step blind.
  • Carry a rollback. Know the exact command or commit that undoes the step before you take it.
  • Re-verify after every step. Build and run the tests; a green pre-flight that you never re-check proves nothing.
  • One logical change per step. A migration, an upgrade, a bump - keep them atomic so a break bisects cleanly.

Assess blast radius with serena (find_symbol, find_referencing_symbols) or the LSP. Do not Read whole files hunting for who touches a type - that is exactly the work the symbol tools do faster.

Flow A - EF Core schema migration

  1. See where you are. dotnet ef migrations list shows what is applied versus pending. Use serena to find the entities you are about to change and everything that references them.
  2. Generate one named migration. dotnet ef migrations add <Name> - name it Verb-then-subject so the history reads as a log: AddOrderShippedAt, MakeEmailUnique, DropLegacyStatus. The one-change-per-migration discipline itself is database-conventions's to state; this step is just the EF naming and generation mechanics.
  3. Preview the SQL. dotnet ef migrations script --idempotent (or --idempotent <from> <to> for a range). Read it for the dangerous shapes: dropped or renamed columns, a non-nullable add with no default, a type narrowing that truncates, an index or constraint added to a large table under a lock. The --idempotent flag guards each step with an __EFMigrationsHistory check so the script is safe to run against a database at any applied state, and re-running it is a no-op. EF cannot see your data - you have to.
  4. Stage destructive change in two deploys. Anything that can lose data or that the old code still depends on is expand-then-contract: first add the new column and backfill (the old code keeps working), ship, then in a later migration drop the old column once nothing reads it. Never collapse both halves into one migration against a live database. A wide backfill is a data migration, not a schema one - run it in batches outside the ALTER, never as a single UPDATE under a table lock.
  5. Apply and verify. In dev, dotnet ef database update, then build and run the tests. For anything past a local box, do not apply from a developer machine or call Database.Migrate() on app start under load (it serializes startup and needs schema-owner rights at runtime). Build a migrations bundle once - dotnet ef migrations bundle -o efbundle (add --self-contained -r <rid> to fold the runtime in too) - and run that single-file executable as a gated deploy step. Like dotnet ef database update it checks __EFMigrationsHistory and applies only the migrations still missing, so it needs neither the SDK, the EF tool, nor the project source on the target and is the zero-downtime artifact.
  6. Know the undo. Roll the database back with dotnet ef database update <PreviousMigration>, then delete the migration files with dotnet ef migrations remove (which un-snapshots cleanly - never delete the files by hand). Never hand-edit an already-applied migration - add a new one. Once a migration has shipped to any shared environment its rollback is a new forward migration, not a remove. Query, tracking, and configuration mechanics live in dotnet-data-access.
Installs
13
GitHub Stars
1
First Seen
Jun 21, 2026
dotnet-migrate — envoydev/claude-stack