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.
DOTNETPROJECTS / DATABASE MIGRATIONS
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.
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");
}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.
Direct provider calls or a fluent builder. Tables, columns, indexes, constraints and data, with raw SQL when you need it.
Compare the APIs ↗Version plans, tags, profiles, maintenance stages, transaction modes and native locks. A CLI or a runner inside your own host.
Choose a runner ↗Track applied versions and give modules separate histories through scopes. Author the reverse for changes that need it.
Understand versioning ↗A PARTICULAR STRENGTH / SQLITE
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 ↗IdINTEGER · PRIMARY KEY
Name255 500 · NOT NULL
↳ Existing rows travel with the schema.
Database.ChangeColumn("Users", new Column("Name", DbType.String, 500)
{
IsNullable = false, DefaultValue = "Unknown",
Collation = Collation.AsciiIgnoreCase
});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
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 ↗dotnet new console -n MigrationDemo -f net9.0
cd MigrationDemo
dotnet add package DotNetProjects.Migrator
dotnet add package Microsoft.Data.Sqlite --version 9.0.7dotnet new console -n MigrationDemo -f net9.0
cd MigrationDemo
dotnet add package DotNetProjects.Migrator
dotnet add package Microsoft.Data.Sqlite --version 9.0.7Shared commands · both styles
THE MIGRATION MANUAL
Detailed guides, paired examples, and provider notes.
Browse every chapter ↗
Tables, columns, data, indexes and constraints.
02 / EXECUTIONConfiguration, transactions, DI, CLI and SQL preview.
03 / DATABASESStorage behavior, SQLite rebuilds and engine differences.
04 / PRACTICEReversals, conditional changes, testing and upgrades.
BRING YOUR DATABASE
Capabilities follow the database engine. The provider guide explains aliases, drivers and operation-specific behavior.
TEST RESULTS AND CODE COVERAGE
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
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.
| 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.
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.
EF Core: a natural fit when an EF model defines your schema and you want migration scaffolding, SQL generation and deployment bundles.
DbUp: compose a script runner in .NET. Evolve: convention-based versioned SQL, checksum validation and repeatable scripts.
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.
EXPLICIT CHANGES. A LASTING RECORD.