DOTNETPROJECTS / DATABASE MIGRATIONS

Database changes,
written in C#.

A table today. A different table tomorrow. Keep every change explicit, versioned, and close to your application.

Choose Classic or Fluent migrations. Bring your ADO.NET driver. Run the same migration system alongside any ORM—or without one.

ONE CHANGE. TWO WAYS TO WRITE IT.001 ↘
CreateUsers.cs

Classic

using System.Data;
using DotNetProjects.Migrator.Framework;

[Migration(1)]
public class CreateUsers : Migration
{
    public override void Up()
    {
        Database.AddTable("Users",
            new Column("Id", DbType.Int32) { IsNullable = false },
            new Column("Name", DbType.String, 255),
            new PrimaryKeyConstraint("PK_Users", "Id"));
    }

    public override void Down() => Database.RemoveTable("Users");
}

Fluent

using DotNetProjects.Migrator.Framework;
using DotNetProjects.Migrator.Framework.Fluent;

[Migration(1)]
public class CreateUsers : FluentMigration
{
    public override void BuildUp(MigrationBuilder migration)
    {
        migration.Create.Table("Users")
            .WithColumn("Id").AsInt32().NotNullable()
            .WithColumn("Name").AsString(255)
            .WithPrimaryKey("PK_Users", "Id");
    }

    public override void BuildDown(MigrationBuilder migration)
        => migration.Delete.Table("Users");
}

Choose one authoring style

01 / AUTHORWrite a numbered change.

02 / REVIEWPlan the next step.

03 / APPLYLeave a lasting record.

SMALL PRIMITIVES. REAL DATABASES.

Your schema.
Your decisions.

01

Two C# styles

Direct provider calls or a fluent builder. Tables, columns, indexes, constraints and data, with raw SQL when you need it.

Compare the APIs ↗
02

A deliberate deployment

Version plans, tags, profiles, maintenance stages, transaction modes and native locks. A CLI or a runner inside your own host.

Choose a runner ↗
03

History with boundaries

Track applied versions and give modules separate histories through scopes. Author the reverse for changes that need it.

Understand versioning ↗

A PARTICULAR STRENGTH / SQLITE

A small database.
Room to evolve.

Change the schema you have. Without an ORM model.

Migrator reads SQLite’s live schema and automatically reconstructs tables for supported changes to column types, defaults and nullability, and primary, foreign, unique and check constraints.

Existing rows are copied and supported schema artifacts are preserved. You describe the change; the provider handles the rebuild.

FluentMigrator requires manual reconstruction for general column alterations and later foreign-key changes. DbUp and Evolve leave it to your scripts. EF Core also rebuilds tables, using model metadata.

Read the SQLite guide and preservation limits ↗
See the sourced operation comparison →
TABLE / UsersΔ 002

IdINTEGER · PRIMARY KEY

Name255 500 · NOT NULL

↳ Existing rows travel with the schema.

Change a column on an existing SQLite table

Classic

Database.ChangeColumn("Users", new Column("Name", DbType.String, 500)
{
    IsNullable = false, DefaultValue = "Unknown",
    Collation = Collation.AsciiIgnoreCase
});

Fluent

migration.Alter.Column("Name").OnTable("Users")
    .AsString(500).NotNullable().WithDefaultValue("Unknown")
    .WithCollation(Collation.AsciiIgnoreCase);

Inside Up() / BuildUp(MigrationBuilder migration)

FROM EMPTY FOLDER TO FIRST TABLE

Start with
one change.

Install the library and your database driver. Add the migration above, wire up the runner, and apply it. SQLite makes a convenient first database.

Follow the complete quick start ↗
Terminal · either authoring style

Classic

dotnet new console -n MigrationDemo -f net9.0
cd MigrationDemo
dotnet add package DotNetProjects.Migrator
dotnet add package Microsoft.Data.Sqlite --version 9.0.7

Fluent

dotnet new console -n MigrationDemo -f net9.0
cd MigrationDemo
dotnet add package DotNetProjects.Migrator
dotnet add package Microsoft.Data.Sqlite --version 9.0.7

Shared commands · both styles

THE MIGRATION MANUAL

Past “hello, table.”

Detailed guides, paired examples, and provider notes.
Browse every chapter ↗

BRING YOUR DATABASE

One migration system.
Many dialects.

Capabilities follow the database engine. The provider guide explains aliases, drivers and operation-specific behavior.

TEST RESULTS AND CODE COVERAGE

Evidence from CI.

The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Counts represent test executions across the matrix; skipped tests are shown separately. Line and branch coverage measure production code across the combined suites.

Code coverage unavailable for this run: no merged coverage artifact is available.

CI run · f3a1cd0 · 2026-09-24T13:48:34Z · workflow: failure. Latest completed master run at deployment time.

THE .NET MIGRATION LANDSCAPE

Choose by how you work.

Feature comparison · Reviewed 23 September 2026
Read the sources and qualifications ↓

Use fluent operations, version planning, a SQL-preview subset, runner options, native locks and the CLI. Read the runner guide and provider limits.

Migrator fits applications that want explicit C# migrations and scoped history without coupling schema changes to an ORM. Other tools offer different authoring and deployment workflows.

Read the detailed feature comparison (Markdown) →
Explore SQLite emulation, preservation limits and framework differences →

Scroll horizontally to compare all five frameworks on smaller screens.

Built-in capabilities and documented workflows. “Custom” means application code or configuration is needed.
Capability Migrator.NET DotNetProjects forkSource [1] FluentMigrator Sources [2] EF Core Sources [3] DbUp Sources [4] Evolve Sources [5]
Authoring style Imperative C# + structured fluent API Handwritten C#
Fluent DSL
C# generated from model changes; editable SQL scripts; C# scripts also supported Versioned SQL files
ORM-independent workflow Yes Yes Uses EF model and DbContext Yes Yes
Generate migrations from model differences No built-in generator Hand-authored Yes — model snapshots Hand-authored Hand-authored
Raw SQL ExecuteNonQuery / fluent Execute.Sql / scripts Execute.Sql / scripts migrationBuilder.Sql Primary workflow Primary workflow
Downgrade an applied version Authored Down() or supported automatic reversal Down(); auto-reverse for supported expressions Down(); target an earlier migration Forward fixes; custom undo workflow Forward fixes; no Down command
History / module separation Scope-filtered discovery + history Custom version tables + migration filtering Separate contexts / migrations + custom history tables Separate journals + script filtering Metadata table/schema + script locations
Transactions Per migration by default; none or whole session (SQLite, PostgreSQL, SQL Server) Per migration by default; configurable Most migrations wrapped automatically Opt-in per script or whole run; none by default Per migration by default; whole-run option
Execution / deployment Library + CLI In-process runner + CLI CLI, SQL scripts, bundles, runtime API Library; host in a console app or application .NET library, .NET tool, CLI
Database abstraction Provider dialects for schema operations Provider-specific SQL generators Relational providers; migrations may differ by provider Database integrations; you write dialect-specific SQL Database integrations; you write dialect-specific SQL
Repeatable / recurring work Ordered maintenance + named profiles; no checksum repeatables Maintenance migrations / profiles Seeding APIs (EF 9+); custom code RunAlways scripts Repeatable SQL reruns on checksum change
Automatic SQLite reconstruction Live-schema rebuilds; no ORM model Manual for general column and foreign-key alterations Rebuilds for model-represented artifacts Author scripts Author scripts
Planning and SQL preview Read-only version plan; connected/offline SQL subset Preview/output Generated SQL scripts Authored SQL / pending scripts Authored SQL
Deployment coordination Opt-in native locks: SQL Server, PostgreSQL, MySQL/MariaDB Application-lock pattern / deployment orchestration Migration locking; execution-path dependent Host/provider concern Cluster setting; provider-dependent

Rollback has two meanings. Reversing an already applied migration uses authored reverse operations. Rolling back a failed transaction depends on the database’s DDL support. Neither restores data removed by a successful destructive migration.

Recurring work is not the same as change detection. Evolve stores script checksums and validates changes; Migrator records versions and scopes without built-in content checksum validation. Maintenance hooks, seeding and RunAlways have different execution rules.

Keep migrations in C#

Migrator: imperative and fluent schema operations, scoped history, tags/profiles, and the CLI or your own host. FluentMigrator: a fluent DSL with packaged runners, tags and profiles.

Let the model drive changes

EF Core: a natural fit when an EF model defines your schema and you want migration scaffolding, SQL generation and deployment bundles.

Keep SQL as the source

DbUp: compose a script runner in .NET. Evolve: convention-based versioned SQL, checksum validation and repeatable scripts.

Sources & comparison methodology

Our column is based on the current repository source, which targets net9.0. Other columns summarize official documentation reviewed on 22 September 2026, with SQLite comparisons rechecked on 23 September, rather than claiming parity across every released package. Check your chosen release, provider and database version. Suitability notes are our interpretation of these documented capabilities.

  1. DotNetProjects.Migrator: target framework, runner, execution and transactions, history and schema operations, migration discovery.
  2. FluentMigrator: quick start and runners, configuration and version tables, auto-reversing migrations, maintenance migrations, profiles, SQLite generator, authoring and providers.
  3. EF Core: model snapshots, authoring and transactions, scripts, bundles and downgrade, custom history tables, multiple providers, seeding, SQLite rebuilds and locking.
  4. DbUp: execution, transactions, journaling, script types, forward-change philosophy, SQL and C# script providers.
  5. Evolve: commands, checksums, repeatables and transactions, configuration, execution options.

EXPLICIT CHANGES. A LASTING RECORD.

The next version
starts with a change.

Open the manual ↗Contribute on GitHub →