FluentMigrator
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。
支持的數據庫列表
- Microsoft SQL Server 2017
- Microsoft SQL Server 2016
- Microsoft SQL Server 2014
- Microsoft SQL Server 2008
- Microsoft SQL Server 2005
- Microsoft SQL Server 2000
- Microsoft SQL Server Compact Edition
- PostgreSQL
- MySQL 4
- MySQL 5
- Oracle
- Oracle (managed ADO.NET)
- Oracle (DotConnect ADO.NET)
- Microsoft JET Engine (Access)
- SQLite
- Firebird
- Amazon Redshift
- SAP Hana
- SAP SQL Anywhere
- DB2
- DB2 iSeries
Fluent Migrator提供了5個不同的類庫來支持不同的場景。
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數據庫添加一個日志表。
創建控制臺程序
我們使用.NET Core CLI創建一個.NET Core的命令行程序。
1
2
3
4
5
6
7
8
9
10
11
|
# 遷移腳本基礎庫 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的表,這里需要創建一個數據庫遷移類
- Log表中有2個字段,一個是Id字段,一個是Text字段
- Id字段是Int64類型的主鍵,且自增
- Text字段是字符串字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
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" ); } } } |
運行遷移類
編寫完遷移類之后,我們就可以開始運行遷移類了。
Fluent Migrator有兩種運行遷移腳本的方式。
- 使用進程內執行器(推薦)
- 使用進程外執行器
使用進程內執行器
所謂的進行內執行器,其實就是借助FluentMigrator.Runner庫,在程序內部手動調用IMigrationRunner接口對象的MigrateUp方法執行數據庫遷移。
這里我們可以修改Program.cs文件如下。
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
|
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這個工具
1
|
dotnet tool install -g FluentMigrator.DotNet.Cli |
安裝完成之后,我們就可以使用這個工具來做數據庫遷移了
1
|
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中的一些基本概念。
遷移(Migrations)
Fluent Migrator中最基礎的元素是遷移類,每個遷移類都需要繼承自一個名為Migration的抽象類,并實現兩個抽象方法Up和Down, 顧名思義Up方法即執行當前的數據庫變更,Down方法即回滾當前的數據庫變更。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
[Migration(1)] public class CreateUserTable : Migration { public override void Up() { Create.Table( "Users" ); } public override void Down() { Delete.Table( "Users" ); } } |
這里你可能注意到遷移類的頭部,有一個Migration的特性,它的值是1, 這里其實是指定了遷移類執行的順序,編號越小的遷移類越先執行(有一部分開發人員系統會使用當前日期的yyyyMMddHHmmss格式來標記遷移類),這個編號必須是唯一的,不能重復。
Fluent接口(Fluent Interface)
Fluent Migrator提供非常豐富的fluent api, 我們可以使用這些api來創建表,列,索引。 基本上你能用到的大部分場景它都支持。
創建表達式(Create Expression)
你可以使用它創建表達式來添加表,列,索引,外鍵,組織結構(schema)
1
2
3
|
Create.Table( "Users" ) .WithIdColumn() .WithColumn( "Name" ).AsString().NotNullable(); |
注:WithIdColumn()是一個擴展方法,它等價于.WithColumn("Id").AsInt32().NotNullable().PrimaryKey().Identity();
1
2
3
|
Create.ForeignKey() .FromTable( "Users" ).ForeignColumn( "CompanyId" ) .ToTable( "Company" ).PrimaryColumn( "Id" ); |
變更表達式(Alter Expression)
用來變更已存在的表和列
1
2
3
4
|
Alter.Table( "Bar" ) .AddColumn( "SomeDate" ) .AsDateTime() .Nullable(); |
1
2
3
4
|
Alter.Table( "Bar" ) .AlterColumn( "SomeDate" ) .AsDateTime() .NotNullable(); |
1
2
3
4
|
Alter.Column( "SomeDate" ) .OnTable( "Bar" ) .AsDateTime() .NotNullable(); |
刪除表達式(Delete Expression)
用來刪除表,列,外鍵,組織結構(Schema)
1
|
Delete.Table( "Users" ); |
刪除多個列(Delete Multiple Columns)
Fluent Migrator也提供了一個刪除多列的語法
1
|
Delete.Column( "AllowSubscription" ).Column( "SubscriptionDate" ).FromTable( "Users" ); |
執行腳本(Execute Expression)
允許你執行自定義的SQL腳本或執行指定的SQL腳本文件
1
2
3
|
Execute.Script( "myscript.sql" ); Execute.EmbeddedScript( "UpdateLegacySP.sql" ); Execute.Sql( "DELETE TABLE Users" ); |
這里EmbeddedScript方法也是執行指定的SQL腳本文件,但是它的文件來源Embbed Resource中讀取。如果你想使用EmbbedScript只需要將指定的SQL腳本文件的Build Action屬性設置為Embbed Resource即可。
重命名表達式(Rename Expression)
允許重命名表或列
1
2
|
Rename.Table( "Users" ).To( "UsersNew" ); Rename.Column( "LastName" ).OnTable( "Users" ).To( "Surname" ); |
數據操作表達式(Data Expressions)
允許對數據庫數據進行新增/修改/刪除操作
1
|
Insert.IntoTable( "Users" ).Row( new { FirstName = "John" , LastName = "Smith" }); |
1
2
3
|
Delete.FromTable( "Users" ).AllRows(); //刪除所有行 Delete.FromTable( "Users" ).Row( new { FirstName = "John" }); //刪除所有FirstName = John的數據行 Delete.FromTable( "Users" ).IsNull( "Username" ); //刪除所有Username為空的數據行 |
1
|
Update.Table( "Users" ).Set( new { Name = "John" }).Where( new { Name = "Johnanna" }); |
數據庫類型判斷表達式(IfDatabase Expression)
允許根據數據庫類型,執行不同的數據庫遷移操作
1
2
3
4
5
6
7
8
9
|
IfDatabase( "SqlServer" , "Postgres" ) .Create.Table( "Users" ) .WithIdColumn() .WithColumn( "Name" ).AsString().NotNullable(); IfDatabase( "Sqlite" ) .Create.Table( "Users" ) .WithColumn( "Id" ).AsInt16().PrimaryKey() .WithColumn( "Name" ).AsString().NotNullable(); |
組織結構存在表達式(Schema.Exists Expressions)
用來判斷組織結構是否已經存在,列如判斷表是否存在,列是否存在等等。
1
2
3
4
|
if (!Schema.Table( "Users" ).Column( "FirstName" ).Exists()) { this .Create.Column( "FirstName" ).OnTable( "Users" ).AsAnsiString(128).Nullable(); } |
配置(Profile)
Fluent Migrator還提供了一個Profile的特性,使用該配置,開發人員可以對針對的不同的環境(開發環境,測試環境,生產環境等)運行不同的腳本。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
[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 } } |
和EF/EF Core的腳本遷移比較
Fluent Migrator的數據庫腳本遷移與EF/EF Core非常類似。
相似點:
- 當我們使用EF/EF Core做數據庫遷移的時候,會在當前數據庫中創建一個__EFMigrationsHistory表,并在其中保存運行過的腳本Id。
- 當我們使用Fluent Migrator做數據庫遷移的時候,也會在數據庫中創建一個VersionInfo表,并在其中保存運行過的腳本Id
區別:
- EF/EF Core的遷移腳本是根據EF上下文配置以及最新的ModelSnapshot自動生成的,更方便一些。Fluent Migrator的遷移腳本,都需要自己手動編寫, 更靈活一些。
- EF/EF Core每次自動生成的遷移文件一個cs文件一個Design.cs文件,每個cs文件中包含了自動生成的腳本類,Design.cs里面包含了針對當前遷移類的最新ModelSnapshot, 所以重度使用EF/EF Core, 最后累計生成的Design.cs文件都會非常大。Fluent Migrator的每個遷移類都是自己編寫的,只包含本次遷移的內容,所以體積更小。
總結
本篇中我描述了Fluent Migrator的一些基本用法,以及它與EF/EF Core腳本遷移的區別, 如果你不是重度EF/EF Core的使用者,可以嘗試一下使用Fluent Migrator來做數據庫遷移。
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對服務器之家的支持。
原文鏈接:http://www.cnblogs.com/lwqlun/p/10649949.html