如何使用FluentMigrator進行數據庫遷移

標題:如何使用FluentMigrator進行數據庫遷移
地址:http://www.javashuo.com/article/p-oxqkzhdd-km.html
做者: Lamond Luhtml

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。mysql

支持的數據庫列表

  • 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個不一樣的類庫來支持不一樣的場景。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的表,這裏須要建立一個數據庫遷移類數據庫

  • Log表中有2個字段,一個是Id字段,一個是Text字段
  • Id字段是Int64類型的主鍵,且自增
  • Text字段是字符串字段
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中的一些基本概念。

遷移(Migrations)

Fluent Migrator中最基礎的元素是遷移類,每一個遷移類都須要繼承自一個名爲Migration的抽象類,並實現兩個抽象方法UpDown, 顧名思義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接口(Fluent Interface)

Fluent Migrator提供很是豐富的fluent api, 咱們可使用這些api來建立表,列,索引。 基本上你能用到的大部分場景它都支持。

建立表達式(Create Expression)

你可使用它建立表達式來添加表,列,索引,外鍵,組織結構(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 Expression)

用來變動已存在的表和列

Alter.Table("Bar")
    .AddColumn("SomeDate")
    .AsDateTime()
    .Nullable();
Alter.Table("Bar")
    .AlterColumn("SomeDate")
    .AsDateTime()
    .NotNullable();
Alter.Column("SomeDate")
    .OnTable("Bar")
    .AsDateTime()
    .NotNullable();

刪除表達式(Delete Expression)

用來刪除表,列,外鍵,組織結構(Schema)

Delete.Table("Users");

刪除多個列(Delete Multiple Columns)

Fluent Migrator也提供了一個刪除多列的語法

Delete.Column("AllowSubscription").Column("SubscriptionDate").FromTable("Users");

執行腳本(Execute Expression)

容許你執行自定義的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 Expression)

容許重命名錶或列

Rename.Table("Users").To("UsersNew");
Rename.Column("LastName").OnTable("Users").To("Surname");

數據操做表達式(Data Expressions)

容許對數據庫數據進行新增/修改/刪除操做

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 Expression)

容許根據數據庫類型,執行不一樣的數據庫遷移操做

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)

用來判斷組織結構是否已經存在,列如判斷表是否存在,列是否存在等等。

if (!Schema.Table("Users").Column("FirstName").Exists())
{
    this.Create.Column("FirstName").OnTable("Users").AsAnsiString(128).Nullable();
}

配置(Profile)

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
    }
}

和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來作數據庫遷移。

相關文章
相關標籤/搜索