Creating a project
dotnet new console --name test
Adding the NuGet packages
# For migration development
dotnet add package FluentMigrator
# For migration execution
dotnet add package FluentMigrator.Runner
# For database support
dotnet add package FluentMigrator.Runner.SQLite
# ADO.NET support for the database
dotnet add package Microsoft.Data.Sqlite
Note
In versions older than 4.0, the FluentMigrator.Runner
package
references all database-specific packages due to backwards
compatibility reasons.
Creating your first migration
Create a file called 20180430_AddLogTable.cs
with the following contents:
using FluentMigrator;
namespace test
{
[Migration(20180430121800)]
public class AddLogTable : Migration
{
public override void Up()
{
Create.Table("Log")
.WithColumn("Id").AsInt64().PrimaryKey().Identity()
.WithColumn("Text").AsString();
}
public override void Down()
{
Delete.Table("Log");
}
}
}
This will create a table named Log
with the columns Id
, and Text
.
Running your first migration
You have two options to execute your migration:
- Using an in-process runner (preferred)
- Using an out-of-process runner (for some corporate requirements)
Note
If you are potentially running migrations from multiple application servers, such as a load balanced set of web servers, you will need to acquire a distributed and exclusive lock, either by database-dependent means or through the use of an external distributed lock coordinator. See the FAQ for more information.
Change your Program.cs
to the following code:
using System;
using System.Linq;
using FluentMigrator.Runner;
using FluentMigrator.Runner.Initialization;
using Microsoft.Extensions.DependencyInjection;
namespace test
{
class Program
{
static void Main(string[] args)
{
using (var serviceProvider = CreateServices())
using (var scope = serviceProvider.CreateScope())
{
// Put the database update into a scope to ensure
// that all resources will be disposed.
UpdateDatabase(scope.ServiceProvider);
}
}
/// <summary>
/// Configure the dependency injection services
/// </summary>
private static ServiceProvider CreateServices()
{
return new ServiceCollection()
// Add common FluentMigrator services
.AddFluentMigratorCore()
.ConfigureRunner(rb => rb
// Add SQLite support to FluentMigrator
.AddSQLite()
// Set the connection string
.WithGlobalConnectionString("Data Source=test.db")
// Define the assembly containing the migrations
.ScanIn(typeof(AddLogTable).Assembly).For.Migrations())
// Enable logging to console in the FluentMigrator way
.AddLogging(lb => lb.AddFluentMigratorConsole())
// Build the service provider
.BuildServiceProvider(false);
}
/// <summary>
/// Update the database
/// </summary>
private static void UpdateDatabase(IServiceProvider serviceProvider)
{
// Instantiate the runner
var runner = serviceProvider.GetRequiredService<IMigrationRunner>();
// Execute the migrations
runner.MigrateUp();
}
}
}
As you can see, instantiating the migration runner (in UpdateDatabase
) becomes
very simple and updating the database is straight-forward.