forked from bittercoder/Migrator.NET
-
-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathindex.html
More file actions
466 lines (461 loc) · 33.5 KB
/
Copy pathindex.html
File metadata and controls
466 lines (461 loc) · 33.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
<!doctype html>
<!-- Generated by .github/scripts/build-docs.py; edit docs/_src/ instead. -->
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="description" content="Classic and Fluent C# migrations. Automatic SQLite schema reconstruction. A complete manual for your next database change."><meta name="theme-color" content="#f4f1e9"><title>Database changes, written in C# · Migrator.NET</title><link rel="icon" href="assets/favicon.svg" type="image/svg+xml"><link rel="stylesheet" href="assets/site.css?v=6a755a5cab9a"><script src="assets/site.js?v=27c2c71534d5" defer></script></head><body class="homepage"><a class="skip" href="#main">Skip to content</a>
<header class="site-header"><div class="header-inner">
<a class="brand" href="index.html" aria-label="Migrator.NET home"><span class="brand-mark" aria-hidden="true">m<span>↗</span></span>Migrator<span class="brand-suffix">.NET</span></a>
<nav aria-label="Main navigation"><a href="guide/index.html">Documentation</a><a href="index.html#sqlite">SQLite</a><a href="index.html#compare">Compare</a><a href="https://github.com/dotnetprojects/Migrator.NET">GitHub ↗</a></nav>
<div class="search-wrap" data-search-index="assets/search-index.json" hidden><form role="search"><label class="sr-only" for="doc-search">Search documentation</label><input id="doc-search" type="search" placeholder="Search the manual…" autocomplete="off" aria-controls="search-results" aria-describedby="search-status"><button aria-label="Search" type="submit">↵</button></form><div class="search-popover" hidden><p id="search-status" role="status"></p><ul id="search-results"></ul></div></div>
</div></header>
<main id="main">
<section class="hero container" aria-labelledby="hero-title">
<div class="hero-copy">
<p class="eyebrow">DOTNETPROJECTS / DATABASE MIGRATIONS</p>
<h1 id="hero-title">Database changes,<br><em>written in C#.</em></h1>
<p class="lead">A table today. A different table tomorrow. Keep every change explicit, versioned, and close to your application.</p>
<p>Choose Classic or Fluent migrations. Bring your ADO.NET driver. Run the same migration system alongside any ORM—or without one.</p>
<div class="hero-actions"><a class="button primary" href="guide/quick-start.html">Write your first migration ↗</a><a class="text-link" href="guide/index.html">Explore the manual →</a></div>
<div class="hero-meta"><a href="https://www.nuget.org/packages/DotNetProjects.Migrator/">Available on NuGet ↗</a><span>.NET 9</span><span>MPL-1.1</span></div>
</div>
<div class="hero-code" id="fluent-api"><div class="file-caption"><span>ONE CHANGE. TWO WAYS TO WRITE IT.</span><span>001 ↘</span></div><div class="code-example" data-example="example-1"><div class="code-toolbar"><span>CreateUsers.cs</span><div class="code-tabs" aria-label="Code style" hidden><button type="button" id="hero-example-1-classic-tab" data-style="classic" aria-controls="hero-example-1-classic">Classic</button><button type="button" id="hero-example-1-fluent-tab" data-style="fluent" aria-controls="hero-example-1-fluent">Fluent</button></div></div><section class="code-panel" id="hero-example-1-classic" data-code-style="classic">
<div class="code-label"><h3>Classic</h3><button type="button" data-copy="hero-example-1-classic-code" hidden aria-label="Copy classic example">Copy</button></div>
<pre tabindex="0" aria-label="CreateUsers.cs, classic"><code id="hero-example-1-classic-code"><span class="syntax-keyword">using</span> System.Data;
<span class="syntax-keyword">using</span> DotNetProjects.Migrator.Framework;
[Migration(<span class="syntax-number">1</span>)]
<span class="syntax-keyword">public</span> <span class="syntax-keyword">class</span> CreateUsers : Migration
{
<span class="syntax-keyword">public</span> <span class="syntax-keyword">override</span> <span class="syntax-keyword">void</span> Up()
{
Database.AddTable(<span class="syntax-string">"Users"</span>,
<span class="syntax-keyword">new</span> Column(<span class="syntax-string">"Id"</span>, DbType.Int32) { IsNullable = <span class="syntax-keyword">false</span> },
<span class="syntax-keyword">new</span> Column(<span class="syntax-string">"Name"</span>, DbType.String, <span class="syntax-number">255</span>),
<span class="syntax-keyword">new</span> PrimaryKeyConstraint(<span class="syntax-string">"PK_Users"</span>, <span class="syntax-string">"Id"</span>));
}
<span class="syntax-keyword">public</span> <span class="syntax-keyword">override</span> <span class="syntax-keyword">void</span> Down() => Database.RemoveTable(<span class="syntax-string">"Users"</span>);
}</code></pre></section><section class="code-panel" id="hero-example-1-fluent" data-code-style="fluent">
<div class="code-label"><h3>Fluent</h3><button type="button" data-copy="hero-example-1-fluent-code" hidden aria-label="Copy fluent example">Copy</button></div>
<pre tabindex="0" aria-label="CreateUsers.cs, fluent"><code id="hero-example-1-fluent-code"><span class="syntax-keyword">using</span> DotNetProjects.Migrator.Framework;
<span class="syntax-keyword">using</span> DotNetProjects.Migrator.Framework.Fluent;
[Migration(<span class="syntax-number">1</span>)]
<span class="syntax-keyword">public</span> <span class="syntax-keyword">class</span> CreateUsers : FluentMigration
{
<span class="syntax-keyword">public</span> <span class="syntax-keyword">override</span> <span class="syntax-keyword">void</span> BuildUp(MigrationBuilder migration)
{
migration.Create.Table(<span class="syntax-string">"Users"</span>)
.WithColumn(<span class="syntax-string">"Id"</span>).AsInt32().NotNullable()
.WithColumn(<span class="syntax-string">"Name"</span>).AsString(<span class="syntax-number">255</span>)
.WithPrimaryKey(<span class="syntax-string">"PK_Users"</span>, <span class="syntax-string">"Id"</span>);
}
<span class="syntax-keyword">public</span> <span class="syntax-keyword">override</span> <span class="syntax-keyword">void</span> BuildDown(MigrationBuilder migration)
=> migration.Delete.Table(<span class="syntax-string">"Users"</span>);
}</code></pre></section><p class="code-caption">Choose one authoring style</p></div></div>
</section>
<div class="history-strip" aria-label="Migration workflow"><div class="container"><p><span>01 / AUTHOR</span>Write a numbered change.</p><span class="history-arrow" aria-hidden="true">→</span><p><span>02 / REVIEW</span>Plan the next step.</p><span class="history-arrow" aria-hidden="true">→</span><p><span>03 / APPLY</span>Leave a lasting record.</p></div></div>
<section class="container section promise-grid" id="schema-api" aria-labelledby="schema-title">
<div><p class="eyebrow">SMALL PRIMITIVES. REAL DATABASES.</p><h2 id="schema-title">Your schema.<br><em>Your decisions.</em></h2></div>
<div class="promise"><span class="item-number">01</span><h3>Two C# styles</h3><p>Direct provider calls or a fluent builder. Tables, columns, indexes, constraints and data, with raw SQL when you need it.</p><a href="guide/api-map.html">Compare the APIs ↗</a></div>
<div class="promise"><span class="item-number">02</span><h3>A deliberate deployment</h3><p>Version plans, tags, profiles, maintenance stages, transaction modes and native locks. A CLI or a runner inside your own host.</p><a href="guide/runners.html">Choose a runner ↗</a></div>
<div class="promise"><span class="item-number">03</span><h3>History with boundaries</h3><p>Track applied versions and give modules separate histories through scopes. Author the reverse for changes that need it.</p><a href="guide/versioning.html">Understand versioning ↗</a></div>
</section>
<section class="sqlite-section" id="sqlite" aria-labelledby="sqlite-title"><div class="container sqlite-grid">
<div><p class="eyebrow">A PARTICULAR STRENGTH / SQLITE</p><h2 id="sqlite-title">A small database.<br><em>Room to evolve.</em></h2><p class="lead">Change the schema you have. Without an ORM model.</p><p>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.</p><p>Existing rows are copied and supported schema artifacts are preserved. You describe the change; the provider handles the rebuild.</p><p class="comparison-note">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.</p><a class="text-link" href="guide/sqlite.html">Read the SQLite guide and preservation limits ↗</a><br><a class="subtle-link" href="https://github.com/dotnetprojects/Migrator.NET/blob/master/docs/migration-framework-comparison.md#sqlite-emulation-comparison">See the sourced operation comparison →</a></div>
<div class="sqlite-workbench"><div class="schema-sketch" aria-label="Example change: Users.Name grows from 255 to 500 characters"><div><span>TABLE / Users</span><span>Δ 002</span></div><p><span class="schema-key">Id</span><span>INTEGER · PRIMARY KEY</span></p><p><span>Name</span><span><s>255</s> <strong>500</strong> · NOT NULL</span></p><p class="schema-retained">↳ Existing rows travel with the schema.</p></div><div class="code-example" data-example="example-51"><div class="code-toolbar"><span>Change a column on an existing SQLite table</span><div class="code-tabs" aria-label="Code style" hidden><button type="button" id="sqlite-example-51-classic-tab" data-style="classic" aria-controls="sqlite-example-51-classic">Classic</button><button type="button" id="sqlite-example-51-fluent-tab" data-style="fluent" aria-controls="sqlite-example-51-fluent">Fluent</button></div></div><section class="code-panel" id="sqlite-example-51-classic" data-code-style="classic">
<div class="code-label"><h3>Classic</h3><button type="button" data-copy="sqlite-example-51-classic-code" hidden aria-label="Copy classic example">Copy</button></div>
<pre tabindex="0" aria-label="Change a column on an existing SQLite table, classic"><code id="sqlite-example-51-classic-code">Database.ChangeColumn(<span class="syntax-string">"Users"</span>, <span class="syntax-keyword">new</span> Column(<span class="syntax-string">"Name"</span>, DbType.String, <span class="syntax-number">500</span>)
{
IsNullable = <span class="syntax-keyword">false</span>, DefaultValue = <span class="syntax-string">"Unknown"</span>,
Collation = Collation.AsciiIgnoreCase
});</code></pre></section><section class="code-panel" id="sqlite-example-51-fluent" data-code-style="fluent">
<div class="code-label"><h3>Fluent</h3><button type="button" data-copy="sqlite-example-51-fluent-code" hidden aria-label="Copy fluent example">Copy</button></div>
<pre tabindex="0" aria-label="Change a column on an existing SQLite table, fluent"><code id="sqlite-example-51-fluent-code">migration.Alter.Column(<span class="syntax-string">"Name"</span>).OnTable(<span class="syntax-string">"Users"</span>)
.AsString(<span class="syntax-number">500</span>).NotNullable().WithDefaultValue(<span class="syntax-string">"Unknown"</span>)
.WithCollation(Collation.AsciiIgnoreCase);</code></pre></section><p class="code-caption">Inside Up() / BuildUp(MigrationBuilder migration)</p></div></div>
</div></section>
<section class="container section start-grid" id="quick-start" aria-labelledby="start-title"><div><p class="eyebrow">FROM EMPTY FOLDER TO FIRST TABLE</p><h2 id="start-title">Start with<br><em>one change.</em></h2><p>Install the library and your database driver. Add the migration above, wire up the runner, and apply it. SQLite makes a convenient first database.</p><a class="button primary" href="guide/quick-start.html">Follow the complete quick start ↗</a></div><div class="code-example" data-example="example-2"><div class="code-toolbar"><span>Terminal · either authoring style</span><div class="code-tabs" aria-label="Code style" hidden><button type="button" id="install-example-2-classic-tab" data-style="classic" aria-controls="install-example-2-classic">Classic</button><button type="button" id="install-example-2-fluent-tab" data-style="fluent" aria-controls="install-example-2-fluent">Fluent</button></div></div><section class="code-panel" id="install-example-2-classic" data-code-style="classic">
<div class="code-label"><h3>Classic</h3><button type="button" data-copy="install-example-2-classic-code" hidden aria-label="Copy classic example">Copy</button></div>
<pre tabindex="0" aria-label="Terminal · either authoring style, classic"><code id="install-example-2-classic-code">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</code></pre></section><section class="code-panel" id="install-example-2-fluent" data-code-style="fluent">
<div class="code-label"><h3>Fluent</h3><button type="button" data-copy="install-example-2-fluent-code" hidden aria-label="Copy fluent example">Copy</button></div>
<pre tabindex="0" aria-label="Terminal · either authoring style, fluent"><code id="install-example-2-fluent-code">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</code></pre></section><p class="code-caption">Shared commands · both styles</p></div></section>
<section class="manual-preview container section" aria-labelledby="manual-title"><div class="section-heading"><div><p class="eyebrow">THE MIGRATION MANUAL</p><h2 id="manual-title">Past “hello, table.”</h2></div><p>Detailed guides, paired examples, and provider notes.<br><a href="guide/index.html">Browse every chapter ↗</a></p></div><div class="chapter-preview"><a href="guide/creating-tables.html"><span>01 / AUTHORING</span><h3>Shape the schema ↗</h3><p>Tables, columns, data, indexes and constraints.</p></a><a href="guide/configuration.html"><span>02 / EXECUTION</span><h3>Control the run ↗</h3><p>Configuration, transactions, DI, CLI and SQL preview.</p></a><a href="guide/providers.html"><span>03 / DATABASES</span><h3>Know your provider ↗</h3><p>Storage behavior, SQLite rebuilds and engine differences.</p></a><a href="guide/testing.html"><span>04 / PRACTICE</span><h3>Ship with evidence ↗</h3><p>Reversals, conditional changes, testing and upgrades.</p></a></div></section>
<section class="provider-section container section" id="providers" aria-labelledby="provider-title"><p class="eyebrow">BRING YOUR DATABASE</p><h2 id="provider-title">One migration system.<br><em>Many dialects.</em></h2><ul class="provider-list"><li><a href="guide/sqlite.html">SQLite</a></li><li><a href="guide/sql-server.html">SQL Server</a></li><li><a href="guide/postgresql.html">PostgreSQL</a></li><li><a href="guide/mysql.html">MySQL</a></li><li><a href="guide/mysql.html">MariaDB</a></li><li><a href="guide/oracle.html">Oracle</a></li><li><a href="guide/other-providers.html">Firebird</a></li><li><a href="guide/other-providers.html">Db2</a></li><li><a href="guide/other-providers.html">Informix</a></li><li><a href="guide/other-providers.html">Sybase</a></li><li><a href="guide/other-providers.html">SAP HANA</a></li><li><a href="guide/other-providers.html">Ingres</a></li></ul><p>Capabilities follow the database engine. The <a href="guide/providers.html">provider guide</a> explains aliases, drivers and operation-specific behavior.</p></section>
<section class="container section ci-section" id="test-results" aria-labelledby="tests-title"><p class="eyebrow">TEST RESULTS AND CODE COVERAGE</p><h2 id="tests-title">Evidence from CI.</h2><p>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.</p><!-- TEST_RESULTS_START -->
<p>Test totals and code coverage are populated during deployment from the latest completed master CI run. <a href="https://github.com/dotnetprojects/Migrator.NET/actions/workflows/dotnetpull.yml?query=branch%3Amaster">View CI runs and test-result artifacts ↗</a>.</p>
<!-- TEST_RESULTS_END --></section>
<section
class="comparison-section"
id="compare"
aria-labelledby="compare-title"
>
<div class="container">
<div class="section-heading">
<div>
<p class="eyebrow">THE .NET MIGRATION LANDSCAPE</p>
<h2 id="compare-title">Choose by how you work.</h2>
</div>
<p>
Feature comparison · Reviewed 23 September 2026<br /><a
href="#sources"
>Read the sources and qualifications ↓</a
>
</p>
</div>
<p class="comparison-intro">
Use fluent operations, version planning, a SQL-preview subset, runner options,
native locks and the CLI.
<a href="guide/runners.html">Read the runner guide and provider limits</a>.
</p>
<p class="comparison-intro">
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.
</p>
<p>
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/docs/migration-framework-comparison.md"
>Read the detailed feature comparison (Markdown) →</a
><br />
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/docs/migration-framework-comparison.md#sqlite-emulation-comparison"
>Explore SQLite emulation, preservation limits and framework
differences →</a
>
</p>
<p class="table-hint" id="table-help">
Scroll horizontally to compare all five frameworks on smaller
screens.
</p>
<div
class="table-scroll"
role="region"
aria-label="Framework feature comparison"
aria-describedby="table-help"
tabindex="0"
>
<table>
<caption>
Built-in capabilities and documented workflows. “Custom” means
application code or configuration is needed.
</caption>
<thead>
<tr>
<th scope="col">Capability</th>
<th scope="col" class="ours">
Migrator.NET <span>DotNetProjects fork</span
><a href="#source-migrator">Source [1]</a>
</th>
<th scope="col">
FluentMigrator <a href="#source-fluent">Sources [2]</a>
</th>
<th scope="col">
EF Core <a href="#source-ef">Sources [3]</a>
</th>
<th scope="col">
DbUp <a href="#source-dbup">Sources [4]</a>
</th>
<th scope="col">
Evolve <a href="#source-evolve">Sources [5]</a>
</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Authoring style</th>
<td class="ours">Imperative C# + structured fluent API</td>
<td>Handwritten C#<br />Fluent DSL</td>
<td>C# generated from model changes; editable</td>
<td>SQL scripts; C# scripts also supported</td>
<td>Versioned SQL files</td>
</tr>
<tr>
<th scope="row">ORM-independent workflow</th>
<td class="ours">Yes</td>
<td>Yes</td>
<td>Uses EF model and DbContext</td>
<td>Yes</td>
<td>Yes</td>
</tr>
<tr>
<th scope="row">
Generate migrations from model differences
</th>
<td class="ours">No built-in generator</td>
<td>Hand-authored</td>
<td>Yes — model snapshots</td>
<td>Hand-authored</td>
<td>Hand-authored</td>
</tr>
<tr>
<th scope="row">Raw SQL</th>
<td class="ours"><code>ExecuteNonQuery</code> / fluent <code>Execute.Sql</code> / scripts</td>
<td><code>Execute.Sql</code> / scripts</td>
<td><code>migrationBuilder.Sql</code></td>
<td>Primary workflow</td>
<td>Primary workflow</td>
</tr>
<tr>
<th scope="row">Downgrade an applied version</th>
<td class="ours">
Authored <code>Down()</code> or supported automatic reversal
</td>
<td>
<code>Down()</code>; auto-reverse for supported expressions
</td>
<td><code>Down()</code>; target an earlier migration</td>
<td>Forward fixes; custom undo workflow</td>
<td>Forward fixes; no Down command</td>
</tr>
<tr>
<th scope="row">History / module separation</th>
<td class="ours">
Scope-filtered discovery + history
</td>
<td>Custom version tables + migration filtering</td>
<td>
Separate contexts / migrations + custom history tables
</td>
<td>Separate journals + script filtering</td>
<td>Metadata table/schema + script locations</td>
</tr>
<tr>
<th scope="row">Transactions</th>
<td class="ours">Per migration by default; none or whole session (SQLite, PostgreSQL, SQL Server)</td>
<td>Per migration by default; configurable</td>
<td>Most migrations wrapped automatically</td>
<td>Opt-in per script or whole run; none by default</td>
<td>Per migration by default; whole-run option</td>
</tr>
<tr>
<th scope="row">Execution / deployment</th>
<td class="ours">Library + CLI</td>
<td>In-process runner + CLI</td>
<td>CLI, SQL scripts, bundles, runtime API</td>
<td>Library; host in a console app or application</td>
<td>.NET library, .NET tool, CLI</td>
</tr>
<tr>
<th scope="row">Database abstraction</th>
<td class="ours">Provider dialects for schema operations</td>
<td>Provider-specific SQL generators</td>
<td>
Relational providers; migrations may differ by provider
</td>
<td>Database integrations; you write dialect-specific SQL</td>
<td>Database integrations; you write dialect-specific SQL</td>
</tr>
<tr>
<th scope="row">Repeatable / recurring work</th>
<td class="ours">Ordered maintenance + named profiles; no checksum repeatables</td>
<td>Maintenance migrations / profiles</td>
<td>Seeding APIs (EF 9+); custom code</td>
<td><code>RunAlways</code> scripts</td>
<td>Repeatable SQL reruns on checksum change</td>
</tr>
<tr>
<th scope="row">Automatic SQLite reconstruction</th>
<td class="ours">Live-schema rebuilds; no ORM model</td>
<td>Manual for general column and foreign-key alterations</td>
<td>Rebuilds for model-represented artifacts</td>
<td>Author scripts</td>
<td>Author scripts</td>
</tr>
<tr>
<th scope="row">Planning and SQL preview</th>
<td class="ours">Read-only version plan; connected/offline SQL subset</td>
<td>Preview/output</td>
<td>Generated SQL scripts</td>
<td>Authored SQL / pending scripts</td>
<td>Authored SQL</td>
</tr>
<tr>
<th scope="row">Deployment coordination</th>
<td class="ours">Opt-in native locks: SQL Server, PostgreSQL, MySQL/MariaDB</td>
<td>Application-lock pattern / deployment orchestration</td>
<td>Migration locking; execution-path dependent</td>
<td>Host/provider concern</td>
<td>Cluster setting; provider-dependent</td>
</tr>
</tbody>
</table>
</div>
<div class="comparison-notes">
<p>
<strong>Rollback has two meanings.</strong> 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.
</p>
<p>
<strong
>Recurring work is not the same as change detection.</strong
>
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.
</p>
</div>
<div class="fit-grid">
<article>
<h3>Keep migrations in C#</h3>
<p>
<strong>Migrator:</strong> imperative and fluent schema operations, scoped
history, tags/profiles, and the CLI or your own host.
<strong>FluentMigrator:</strong> a fluent DSL with packaged
runners, tags and profiles.
</p>
</article>
<article>
<h3>Let the model drive changes</h3>
<p>
<strong>EF Core:</strong> a natural fit when an EF model defines
your schema and you want migration scaffolding, SQL generation
and deployment bundles.
</p>
</article>
<article>
<h3>Keep SQL as the source</h3>
<p>
<strong>DbUp:</strong> compose a script runner in .NET.
<strong>Evolve:</strong> convention-based versioned SQL,
checksum validation and repeatable scripts.
</p>
</article>
</div>
<details class="sources" id="sources">
<summary>Sources & comparison methodology</summary>
<p>
Our column is based on the current repository source, which
targets <code>net9.0</code>. 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.
</p>
<ol>
<li id="source-migrator">
<strong>DotNetProjects.Migrator:</strong>
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/src/Migrator/DotNetProjects.Migrator.csproj"
>target framework</a
>,
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/src/Migrator/Migrator.cs"
>runner</a
>,
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/src/Migrator/MigrationExecution.cs"
>execution and transactions</a
>,
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/src/Migrator/Providers/TransformationProvider.cs"
>history and schema operations</a
>,
<a
href="https://github.com/dotnetprojects/Migrator.NET/blob/master/src/Migrator/MigrationLoader.cs"
>migration discovery</a
>.
</li>
<li id="source-fluent">
<strong>FluentMigrator:</strong>
<a
href="https://fluentmigrator.github.io/intro/quick-start.html"
>quick start and runners</a
>,
<a
href="https://fluentmigrator.github.io/intro/configuration.html"
>configuration and version tables</a
>,
<a
href="https://fluentmigrator.github.io/migration-types/auto-reversing.html"
>auto-reversing migrations</a
>,
<a
href="https://fluentmigrator.github.io/migration-types/maintenance.html"
>maintenance migrations</a
>,
<a
href="https://fluentmigrator.github.io/migration-types/profiles.html"
>profiles</a
>,
<a href="https://github.com/fluentmigrator/fluentmigrator/blob/2e0acdb7c375b03e50e65f34ddf50e44ee45df30/src/FluentMigrator.Runner.SQLite/Generators/SQLite/SQLiteGenerator.cs">SQLite generator</a>,
<a href="https://fluentmigrator.github.io/"
>authoring and providers</a
>.
</li>
<li id="source-ef">
<strong>EF Core:</strong>
<a
href="https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/"
>model snapshots</a
>,
<a
href="https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/managing"
>authoring and transactions</a
>,
<a
href="https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/applying"
>scripts, bundles and downgrade</a
>,
<a
href="https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/history-table"
>custom history tables</a
>,
<a
href="https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/providers"
>multiple providers</a
>,
<a
href="https://learn.microsoft.com/en-us/ef/core/modeling/data-seeding"
>seeding</a
>,
<a href="https://learn.microsoft.com/en-us/ef/core/providers/sqlite/limitations">SQLite rebuilds and locking</a>.
</li>
<li id="source-dbup">
<strong>DbUp:</strong>
<a href="https://dbup.readthedocs.io/en/latest/">execution</a>,
<a
href="https://dbup.readthedocs.io/en/latest/more-info/transactions/"
>transactions</a
>,
<a
href="https://dbup.readthedocs.io/en/latest/more-info/journaling/"
>journaling</a
>,
<a
href="https://dbup.readthedocs.io/en/latest/more-info/script-types/"
>script types</a
>,
<a
href="https://dbup.readthedocs.io/en/latest/philosophy-behind-dbup/"
>forward-change philosophy</a
>,
<a
href="https://dbup.readthedocs.io/en/latest/more-info/script-providers/"
>SQL and C# script providers</a
>.
</li>
<li id="source-evolve">
<strong>Evolve:</strong>
<a href="https://evolve-db.netlify.app/concepts/"
>commands, checksums, repeatables and transactions</a
>,
<a href="https://evolve-db.netlify.app/configuration/options/"
>configuration</a
>,
<a href="https://evolve-db.netlify.app/getting-started/"
>execution options</a
>.
</li>
</ol>
</details>
</div>
</section>
<section class="closing-section container"><p class="eyebrow">EXPLICIT CHANGES. A LASTING RECORD.</p><h2>The next version<br><em>starts with a change.</em></h2><a class="button primary" href="guide/quick-start.html">Open the manual ↗</a><a class="text-link" href="https://github.com/dotnetprojects/Migrator.NET">Contribute on GitHub →</a></section>
</main>
<footer class="site-footer"><a class="brand" href="index.html">Migrator.NET</a><p>Explicit changes. A lasting record.<br>DotNetProjects · MPL-1.1</p><a href="guide/quick-start.html">Write your first migration ↗</a></footer><span id="copy-status" class="sr-only" role="status" aria-live="polite"></span>
</body></html>