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.
DOTNETPROJECTS / MIGRATOR.NET
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.
[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");
}
}
SMALL API. EXPLICIT CONTROL.
Define tables, columns, indexes and constraints through a transformation API or structured fluent builders. Use raw SQL when a change needs database-specific behavior.
Number your migrations, implement Up() and
Down(), and migrate to a chosen version. Applied
migrations are recorded in the database.
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
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
A minimal SQLite example for unreleased v13 source.
Use .NET 9 and a checkout of this repository.
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 ↗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
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.
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");
}
}
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.
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
Use fluent and imperative migrations in the same assembly and runner.
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.
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
Supply your ADO.NET driver.
Migrator supplies the schema
operations.
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
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
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.
| 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.
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.
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, 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.
CONTINUING MIGRATOR.NET
DotNetProjects.Migrator continues the original Migrator.NET project, bringing together fork contributions with work on SQLite schema handling, provider independence and migration scopes.