skills/data/ef-migrations/SKILL.md
Use when creating, applying, or managing EF Core database migrations.
npx skillsauth add faysilalshareef/dotnet-ai-kit ef-migrationsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
# Add a new migration
dotnet ef migrations add CreateOrdersTable \
--project src/{Company}.{Domain}.Infrastructure \
--startup-project src/{Company}.{Domain}.WebApi
# Generate idempotent SQL script for production
dotnet ef migrations script --idempotent \
--project src/{Company}.{Domain}.Infrastructure \
--startup-project src/{Company}.{Domain}.WebApi \
--output migrations.sql
# Remove last unapplied migration
dotnet ef migrations remove \
--project src/{Company}.{Domain}.Infrastructure
public partial class SeedOrderStatuses : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.InsertData(
table: "OrderStatuses",
columns: ["Id", "Name", "Description"],
values: new object[,]
{
{ 1, "Draft", "Order is being prepared" },
{ 2, "Submitted", "Order has been submitted" },
{ 3, "Processing", "Order is being processed" },
{ 4, "Shipped", "Order has been shipped" },
{ 5, "Delivered", "Order has been delivered" },
{ 6, "Cancelled", "Order was cancelled" }
});
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DeleteData(
table: "OrderStatuses",
keyColumn: "Id",
keyValues: [1, 2, 3, 4, 5, 6]);
}
}
// Program.cs — development only
if (app.Environment.IsDevelopment())
{
using var scope = app.Services.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<AppDbContext>();
await db.Database.MigrateAsync();
}
# GitHub Actions — apply migrations before deployment
- name: Apply Migrations
run: |
dotnet ef database update \
--project src/{Company}.{Domain}.Infrastructure \
--startup-project src/{Company}.{Domain}.WebApi \
--connection "${{ secrets.DB_CONNECTION_STRING }}"
# Alternative: use idempotent SQL script
- name: Generate Migration Script
run: |
dotnet ef migrations script --idempotent \
--project src/{Company}.{Domain}.Infrastructure \
--startup-project src/{Company}.{Domain}.WebApi \
--output ${{ runner.temp }}/migrate.sql
- name: Apply Migration Script
uses: azure/sql-action@v2
with:
connection-string: ${{ secrets.DB_CONNECTION_STRING }}
path: ${{ runner.temp }}/migrate.sql
# Create a migration bundle executable
dotnet ef migrations bundle \
--project src/{Company}.{Domain}.Infrastructure \
--startup-project src/{Company}.{Domain}.WebApi \
--output efbundle
# Run the bundle (in CI/CD or on the server)
./efbundle --connection "Server=prod;Database=AppDb;..."
internal sealed class AppDbContextFactory
: IDesignTimeDbContextFactory<AppDbContext>
{
public AppDbContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile("appsettings.Development.json", optional: true)
.AddUserSecrets<AppDbContextFactory>(optional: true)
.Build();
var options = new DbContextOptionsBuilder<AppDbContext>()
.UseSqlServer(config.GetConnectionString("Default"))
.Options;
return new AppDbContext(options);
}
}
// Modular monolith — separate migration history per module
options.UseSqlServer(connectionString, sql =>
{
sql.MigrationsHistoryTable("__EFMigrationsHistory", "orders");
});
Down method implementationsMigrations/ folder in the projectIDesignTimeDbContextFactory<> implementationsDatabase.MigrateAsync() calls in Program.csdotnet ef commandsMigrationsHistoryTable configurationdotnet tool install dotnet-ef --global| Environment | Migration Strategy |
|-------------|-------------------|
| Development | Database.MigrateAsync() at startup |
| CI/Testing | dotnet ef database update in pipeline |
| Staging | Idempotent SQL script or bundle |
| Production | Idempotent SQL script reviewed and applied |
data-ai
Use when about to claim work is complete, fixed, passing, or ready — before committing, creating PRs, or moving to the next task. Requires running verification commands and confirming output before making any success claims.
development
Use when encountering any bug, test failure, build error, or unexpected behavior — before proposing fixes or making changes.
development
Use when checkpointing, wrapping up, or handing off an AI-assisted development session.
development
Use when following the Specification-Driven Development lifecycle from plan through ship.