DOTNETPROJECTS / MIGRATOR.NET

Database changes.
Part of your code.

Write schema changes in C# with imperative or fluent APIs. Version them with your application. Run them with the database provider and ORM you choose.

Build and database tests on master Latest stable NuGet version License: MPL-1.1

Open source · MPL-1.1 · Current source targets .NET 9

001_CreateUsers.csUP / DOWN
[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");
    }
}
PROVIDER DIALECTSSQL ServerPostgreSQLSQLiteMySQL / MariaDBOracleSee all →

SMALL API. EXPLICIT CONTROL.

Your schema has a history.
Keep it in the repository.

01 / AUTHOR

C# without an ORM dependency

Define tables, columns, indexes and constraints through a transformation API or structured fluent builders. Use raw SQL when a change needs database-specific behavior.

02 / VERSION

Move forward. Step back.

Number your migrations, implement Up() and Down(), and migrate to a chosen version. Applied migrations are recorded in the database.

03 / ORGANIZE

Separate histories by scope

Keep module version histories in one database using named scopes. Select each module’s migration assembly or types when you create its runner.

VERSION 13 · SOURCE PREVIEW

Explicit definitions, shared authoring.

Breaking source changes. These features are not yet a released NuGet version.

Define primary, unique, foreign-key and check constraints as table objects. The imperative and fluent APIs share column definitions, trusted SQL defaults and typed collation requests.

new Column("Id", DbType.String, 27)
    { DefaultValue = RawSql.Insert("ksuid_new()") };

builder.Create.Table("Events")
    .WithColumn("Id").AsString(27)
    .WithDefaultValue(RawSql.Insert("ksuid_new()"))
    .WithColumn("Name").AsString(100)
    .WithCollation(Collation.CaseInsensitive);

The target database must supply the SQL function. Collation mappings have explicit provider limits: SQLite ASCII folding does not satisfy a Unicode case-insensitive request. Read the 12.1-to-13 migration guide ↗.

Additional databases require passing real-engine CI. SAP HANA provider qualification ↗; Redshift, Snowflake and Db2 for IBM i remain unsupported.

QUICK START

From code to schema.

A minimal SQLite example for unreleased v13 source.
Use .NET 9 and a checkout of this repository.

1

Reference the v13 source

Run these commands from your Migrator.NET checkout. This example references the source project and passes an open SQLite connection to the provider.

View package versions on NuGet ↗
Terminal
dotnet new console -n MigrationDemo -f net9.0
cd MigrationDemo
dotnet add reference ../src/Migrator/DotNetProjects.Migrator.csproj
dotnet add package Microsoft.Data.Sqlite --version 9.0.7
2

Describe the change

Add a public migration class. Each version must be unique within the migration set loaded by a runner.

Down() is your explicit reverse operation; dropping a table also removes its data.

CreateUsers.cs
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");
    }
}
3

Run pending migrations

Replace Program.cs with this code, then run dotnet run. The runner discovers the migration in your assembly and records it under the default scope.

Subsequent runs skip applied versions. Use MigrateTo(version) to target an earlier or later version.

Program.cs
using DotNetProjects.Migrator;
using DotNetProjects.Migrator.Providers;
using Microsoft.Data.Sqlite;

using var connection = new SqliteConnection("Data Source=app.db");
connection.Open();

using var provider = ProviderFactory.Create(
    ProviderTypes.SQLite, connection, defaultSchema: null);

var migrator = new Migrator(
    provider, typeof(CreateUsers).Assembly, trace: false);

if (migrator.LastAppliedMigrationVersion is long applied
    && applied > migrator.AssemblyLastMigrationVersion)
{
    throw new InvalidOperationException(
        "Database version is newer than this application.");
}

migrator.MigrateToLastVersion();

FLUENT API · V13 SOURCE PREVIEW

Chain operations. Keep control.

Use fluent and imperative migrations in the same assembly and runner.

The same quick start, written fluently

Replace CreateUsers.cs from step 2 with this class. Keep the source reference and Program.cs from the quick start.

BuildUp collects operations before execution; BuildDown describes the reverse change.

Builders cover tables, columns, keys, indexes, data and SQL. Database support still depends on the provider.

CreateUsers.cs · 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()
            .WithPrimaryKey("PK_Users", "Id")
            .WithColumn("Name").AsString(255);
    }

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

DATABASE PROVIDERS

One API. Multiple dialects.

Supply your ADO.NET driver.
Migrator supplies the schema operations.

Common database families

  • SQL Server
  • PostgreSQL
  • SQLite
  • MySQL
  • MariaDB
  • Oracle

Additional dialects in source

  • IBM Db2
  • IBM Informix
  • Firebird
  • Ingres
  • Sybase
  • SAP HANA (v13 source)

This is an implementation inventory, not a certification of every server or driver version. Schema operations and transactional DDL vary by provider. Check the provider factory and provider tests for your database.

BUILD AND DATABASE TESTS

Evidence from CI.

The CI matrix runs unit tests and 11 database suites, then checks for missing or duplicate test assignments. Results count test executions across the matrix; skipped tests are shown separately.

CI run · 87d4f1f · 2026-09-22T22:23:32Z · workflow: success. Latest completed master run at deployment time.

THE .NET MIGRATION LANDSCAPE

Choose by how you work.

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

Version 13 source preview, not a NuGet release: fluent operations, SQL-preview subset, runner options, native locks and source CLI. Read the runner guide and limitations. Read the merged runner changes.

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 + source CLI (unreleased) 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

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 a source 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, 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, authoring and providers.
  3. EF Core: model snapshots, authoring and transactions, scripts, bundles and downgrade, custom history tables, multiple providers, seeding.
  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.

CONTINUING MIGRATOR.NET

A familiar idea.
A maintained fork.

DotNetProjects.Migrator continues the original Migrator.NET project, bringing together fork contributions with work on SQLite schema handling, provider independence and migration scopes.