標題:如何使用FluentMigrator進行數據庫遷移
地址:http://www.javashuo.com/article/p-oxqkzhdd-km.html
做者: Lamond Luhtml
Fluent Migrator是一個基於.NET的遷移框架,你能夠像使用Ruby on Rails Migrations同樣使用它。Fluent Migrator的最新版本是3.13版,官網地址https://github.com/fluentmigrator/fluentmigrator。 你可使用C#編寫數據庫遷移類,而不須要編寫任何SQL腳本。從使用方式上看,它很是像EF/EF Core的數據庫遷移腳本,可是它支持的數據庫類型比EF/EF Core多的多,且不受限與EF/EF Core。mysql
Fluent Migrator提供了5個不一樣的類庫來支持不一樣的場景。git
Package | 描述 |
---|---|
FluentMigrator | 建立數據庫所需的基礎程序集 |
FluentMigrator.Runner | 進程內執行數據庫遷移所需的程序集 |
FluentMigrator.Console | 進程外執行數據庫遷移所需的程序集,它兼容.NET 4.0/4.5/.NET Core 2.0 |
FluentMigrator.MSBuild | 兼容.NET 4.0/4.5/.NET Standard 2.0的MSBuild任務 |
FluentMigrator.DotNet.Cli | 可執行數據庫遷移的.NET Core CLI工具 |
這裏咱們首先演示一個最簡單的數據庫遷移例子,爲一個MySql數據庫添加一個日誌表。github
咱們使用.NET Core CLI建立一個.NET Core的命令行程序。sql
dotnet new console
接下來,咱們須要添加必要的程序集。shell
# 遷移腳本基礎庫 dotnet add package FluentMigrator # 遷移腳本運行庫 dotnet add package FluentMigrator.Runner # 針對MySQL的遷移腳本支持庫 dotnet add package FluentMigrator.Runner.MySQL # ADO.NET針對MySQL的驅動器 dotnet add package MySQL.Data
未了建立一個名爲Log的表,這裏須要建立一個數據庫遷移類數據庫
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"); } } }
編寫完遷移類以後,咱們就能夠開始運行遷移類了。express
Fluent Migrator有兩種運行遷移腳本的方式。c#
所謂的進行內執行器,其實就是藉助FluentMigrator.Runner
庫,在程序內部手動調用IMigrationRunner
接口對象的MigrateUp
方法執行數據庫遷移。api
這裏咱們能夠修改Program.cs
文件以下。
class Program { static void Main(string[] args) { var serviceProvider = CreateServices(); using (var scope = serviceProvider.CreateScope()) { UpdateDatabase(scope.ServiceProvider); } } private static IServiceProvider CreateServices() { return new ServiceCollection() //添加FluentMigrator基礎服務 .AddFluentMigratorCore() .ConfigureRunner(rb => rb //添加MySql 5.0支持 .AddMySql5() //配置鏈接字符串 .WithGlobalConnectionString("server=localhost;port=3307;Database=abc;UID=root;PWD=123456") //檢索遷移配置 .ScanIn(typeof(AddLogTable).Assembly).For.Migrations()) //啓用控制檯日誌 .AddLogging(lb => lb.AddFluentMigratorConsole()) //構建服務提供器 .BuildServiceProvider(false); } private static void UpdateDatabase(IServiceProvider serviceProvider) { //初始化進程內遷移構建器 var runner = serviceProvider.GetRequiredService<IMigrationRunner>(); //執行遷移腳本 runner.MigrateUp(); } }
啓動程序以後,遷移自動完成。
若是你想使用進行外遷移執行器,這裏首先須要保證你已經安裝了.NET Core 2.1或以上版本的SDK, 由於你須要使用.NET Core 2.1以後新增的Global Tool功能。
這裏咱們可使用命令行,添加FluentMigrator.DotNet.Cli
這個工具
dotnet tool install -g FluentMigrator.DotNet.Cli
安裝完成以後,咱們就可使用這個工具來作數據庫遷移了
dotnet fm migrate -p mysql -c "server=localhost;port=3307;Database=abc;UID=root;PWD=123456" -a ".\bin\Debug\netcoreapp2.1\test.dll"
這個方法有3個參數, 第一個參數-p指定了數據庫的類型,第二個參數-c指定了鏈接字符串,第三個參數-a指定了包含遷移類的程序集路徑。
注意:其實這裏還有第四個參數command, 可選值爲down/up, 若是不指定,默認是up, 即運行全部還未運行過的數據庫遷移類。
方法執行後,效果和進程內執行器的效果一致。
在展現了一個簡單示例以後,咱們接下來看一下Fluent Migrator中的一些基本概念。
Fluent Migrator中最基礎的元素是遷移類,每一個遷移類都須要繼承自一個名爲Migration
的抽象類,並實現兩個抽象方法Up
和Down
, 顧名思義Up
方法即執行當前的數據庫變動,Down
方法即回滾當前的數據庫變動。
[Migration(1)] public class CreateUserTable : Migration { public override void Up() { Create.Table("Users"); } public override void Down() { Delete.Table("Users"); } }
這裏你可能注意到遷移類的頭部,有一個Migration
的特性,它的值是1, 這裏實際上是指定了遷移類執行的順序,編號越小的遷移類越先執行(有一部分開發人員系統會使用當前日期的yyyyMMddHHmmss格式來標記遷移類),這個編號必須是惟一的,不能重複。
Fluent Migrator提供很是豐富的fluent api, 咱們可使用這些api來建立表,列,索引。 基本上你能用到的大部分場景它都支持。
你可使用它建立表達式來添加表,列,索引,外鍵,組織結構(schema)
Create.Table("Users") .WithIdColumn() .WithColumn("Name").AsString().NotNullable();
注:
WithIdColumn()
是一個擴展方法,它等價於.WithColumn("Id").AsInt32().NotNullable().PrimaryKey().Identity();
Create.ForeignKey() .FromTable("Users").ForeignColumn("CompanyId") .ToTable("Company").PrimaryColumn("Id");
用來變動已存在的表和列
Alter.Table("Bar") .AddColumn("SomeDate") .AsDateTime() .Nullable();
Alter.Table("Bar") .AlterColumn("SomeDate") .AsDateTime() .NotNullable();
Alter.Column("SomeDate") .OnTable("Bar") .AsDateTime() .NotNullable();
用來刪除表,列,外鍵,組織結構(Schema)
Delete.Table("Users");
Fluent Migrator也提供了一個刪除多列的語法
Delete.Column("AllowSubscription").Column("SubscriptionDate").FromTable("Users");
容許你執行自定義的SQL腳本或執行指定的SQL腳本文件
Execute.Script("myscript.sql"); Execute.EmbeddedScript("UpdateLegacySP.sql"); Execute.Sql("DELETE TABLE Users");
這裏
EmbeddedScript
方法也是執行指定的SQL腳本文件,可是它的文件來源Embbed Resource中讀取。若是你想使用EmbbedScript只須要將指定的SQL腳本文件的Build Action屬性設置爲Embbed Resource便可。
容許重命名錶或列
Rename.Table("Users").To("UsersNew"); Rename.Column("LastName").OnTable("Users").To("Surname");
容許對數據庫數據進行新增/修改/刪除操做
Insert.IntoTable("Users").Row(new { FirstName = "John", LastName = "Smith" });
Delete.FromTable("Users").AllRows(); //刪除全部行 Delete.FromTable("Users").Row(new { FirstName = "John" }); //刪除全部FirstName = John的數據行 Delete.FromTable("Users").IsNull("Username"); //刪除全部Username爲空的數據行
Update.Table("Users").Set(new { Name = "John" }).Where(new { Name = "Johnanna" });
容許根據數據庫類型,執行不一樣的數據庫遷移操做
IfDatabase("SqlServer", "Postgres") .Create.Table("Users") .WithIdColumn() .WithColumn("Name").AsString().NotNullable(); IfDatabase("Sqlite") .Create.Table("Users") .WithColumn("Id").AsInt16().PrimaryKey() .WithColumn("Name").AsString().NotNullable();
用來判斷組織結構是否已經存在,列如判斷表是否存在,列是否存在等等。
if (!Schema.Table("Users").Column("FirstName").Exists()) { this.Create.Column("FirstName").OnTable("Users").AsAnsiString(128).Nullable(); }
Fluent Migrator還提供了一個Profile
的特性,使用該配置,開發人員能夠對針對的不一樣的環境(開發環境,測試環境,生產環境等)運行不一樣的腳本。
[Profile("Development")] public class CreateDevSeedData : Migration { public override void Up() { Insert.IntoTable( "User" ).Row( new { Username = "devuser1", DisplayName = "Dev User" }); } public override void Down() { //empty, not using } }
Fluent Migrator的數據庫腳本遷移與EF/EF Core很是相似。
類似點:
__EFMigrationsHistory
表,並在其中保存運行過的腳本Id。VersionInfo
表,並在其中保存運行過的腳本Id區別:
ModelSnapshot
自動生成的,更方便一些。Fluent Migrator的遷移腳本,都須要本身手動編寫, 更靈活一些。cs
文件一個Design.cs
文件,每一個cs文件中包含了自動生成的腳本類,Design.cs
裏面包含了針對當前遷移類的最新ModelSnapshot, 因此重度使用EF/EF Core, 最後累計生成的Design.cs文件都會很是大。Fluent Migrator的每一個遷移類都是本身編寫的,只包含本次遷移的內容,因此體積更小。本篇中我描述了Fluent Migrator的一些基本用法,以及它與EF/EF Core腳本遷移的區別, 若是你不是重度EF/EF Core的使用者,能夠嘗試一下使用Fluent Migrator來作數據庫遷移。