zoukankan      html  css  js  c++  java
  • 如何使用FluentMigrator进行数据库迁移

    标题:如何使用FluentMigrator进行数据库迁移
    地址:https://www.cnblogs.com/lwqlun/p/10649949.html
    作者: Lamond Lu

    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的命令行程序。

    dotnet new console
    

    添加程序集

    接下来,我们需要添加必要的程序集。

    # 迁移脚本基础库
    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");
            }
        }
    }
    

    运行迁移类

    编写完迁移类之后,我们就可以开始运行迁移类了。

    Fluent Migrator有两种运行迁移脚本的方式。

    • 使用进程内执行器(推荐)
    • 使用进程外执行器

    使用进程内执行器

    所谓的进行内执行器,其实就是借助FluentMigrator.Runner库,在程序内部手动调用IMigrationRunner接口对象的MigrateUp方法执行数据库迁移。

    这里我们可以修改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 ".inDebug
    etcoreapp2.1	est.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来做数据库迁移。

  • 相关阅读:
    C++_标准模板库STL概念介绍2-泛型编程
    C++_标准模板库STL概念介绍1-建立感性认知
    C++_新特性1-类型转换运算符
    C++_新特性2-RTTI运行阶段类型识别
    C++_异常9-异常的注意事项
    C++_异常8-异常、类和基础
    C++_异常7-exception类
    C++_异常6-其他异常特性
    redis数据类型之—List
    redis数据类型之—Hash
  • 原文地址:https://www.cnblogs.com/lwqlun/p/10649949.html
Copyright © 2011-2022 走看看