Friday, April 25, 2025

Fluent Migrator as a Standalone Option

Why a Stand-Alone FluentMigrator Project Beats EF Core Migrations for PostgreSQL

Modern .NET teams love how Entity Framework Core auto-generates migration scripts, but that convenience can come at a cost—especially when multiple databases, environment-specific tweaks, or non-EF data layers enter the picture.

This post walks through a practical example that swaps EF Core migrations for a dedicated FluentMigrator project plus a lightweight console utility. You’ll see how the combo delivers cleaner workflows, tighter control, and future-proof flexibility without giving up automation.

TL;DR

✔︎ FluentMigrator Console✖︎ EF Core Migrations
Works with any ORM—or noneTied to EF Core only
Multi-database orchestration out of the boxOne migration set per DbContext
Tags & config for dev / test / prodDIY filtering required
Explicit C# scripts (no surprise SQL)Auto SQL can be verbose or inefficient
Fits blue-green / zero-downtime releasesSchema and code deploy together

The Setup

Project Layout

css
src/ ├─ App/ └─ Database.Migrations/ ← standalone FluentMigrator project

Console Utility Highlights

  • Multi-Database Support – Reads a list of databases from appsettings.json and runs migrations for each.

  • Stub Generatorcreate command spits out timestamped C# templates so every migration starts consistent.

  • Flexible Commandsmigrate, rollback, rollback-prev, and rollback-all.

  • Environment Awareness – Pulls DOTNET_ENVIRONMENT / ASPNETCORE_ENVIRONMENT and loads the matching config file.

  • CI/CD Ready – Plays nicely with AWS CodeBuild + Secrets Manager.


Everyday Workflow

1. Define Your Databases

jsonc
// appsettings.json { "FluentMigrator": { "Databases": { "SalesDb": { "Provider": "Postgres", "ConnectionString": "Host=db;Port=5432;Database=sales;Username=app;Password=secret" } } } }

2. Generate a Migration Stub

bash
dotnet run create SalesDb AddUsersTable
csharp
// Migrations/SalesDb/202504211035_SalesDb_AddUsersTable.cs using FluentMigrator; namespace Database.Migrations.Migrations.SalesDb; [Migration(202504211035)] public class SalesDb_202504211035_AddUsersTable : Migration { public override void Up() { Create.Table("Users") .WithColumn("Id").AsInt32().PrimaryKey().Identity() .WithColumn("Name").AsString(100).NotNullable(); } public override void Down() => Delete.Table("Users"); }

3. Apply Migrations

bash
dotnet run migrate # applies pending migrations to every configured DB

4. Roll Back When Needed

bash
dotnet run rollback 202504211035 # jump to a specific version dotnet run rollback-prev # undo the last migration

Why Bother?—Seven Big Wins

1. Decoupled Deployments

Schema changes travel in their own artifact, so blue-green deploys aren’t blocked by code releases. Run a migration on staging, smoke-test it, then promote to production without rebuilding your app container.

2. ORM Freedom

Need Dapper for perf-critical queries? Considering a move away from .NET someday? FluentMigrator is agnostic, so the migrations still work.

3. Total Control

Hand-crafted C# lets you tune every column type and index. No more digging into auto-generated SQL that adds “mysterious” constraints or verbose table renames.

4. Environment-Specific Logic

Use [Tags("Development")] to seed test data or skip heavyweight indexes in dev. Tags run (or don’t) based on the environment—no fragile if-statements scattered through code.

5. Cleaner Pull Requests

Migration classes live in Database.Migrations. Reviewers focus on schema diffs instead of wading through unrelated service code.

6. Multi-Database Made Simple

One config file lists all target DBs. The utility loops through each, so there’s no copy-paste of DbContext projects or juggling multiple EF migration histories.

7. CI/CD Integration

A tiny buildspec.yml is all that’s needed:

yaml
version: 0.2 phases: install: commands: - dotnet tool install -g FluentMigrator.DotNet.Cli build: commands: - dotnet restore - dotnet build Database.Migrations.csproj - export CONNECTION_STRING=$(aws secretsmanager get-secret-value --secret-id salesdb --query SecretString --output text) - dotnet run --project Database.Migrations.csproj migrate

The pipeline builds once, applies migrations, and hands off a schema-ready database to the app deploy stage.


Where EF Core Still Shines

  • Quick prototypes – If everything lives in one small codebase and EF Core already maps your entities, auto-generated migrations might be “good enough.”

  • Simple single-DB apps – No extra project to maintain when the model is small and the team is tiny.

But once multi-DB scenarios, microservices, or strict DevOps pipelines show up, FluentMigrator plus a console orchestrator wins on predictability and control.


Wrap-Up

Automatic migrations feel effortless—until they aren’t. A dedicated FluentMigrator project makes database evolution predictable, testable, and independent of any single framework. Couple it with a smart console utility, and you gain:

  • Cross-database orchestration

  • Environment-aware scripts

  • Precise, human-readable migrations

  • Zero-downtime deploy possibilities

Give it a spin on your next feature branch—you might never look back.

No comments:

Post a Comment

New Features in .Net 10

🚀 Runtime Enhancements Stack Allocation for Small Arrays The Just-In-Time (JIT) compiler now optimizes memory usage by stack-allocating s...