侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

如何利用FluentMigrator实现数据库迁移

数据库  /  管理员 发布于 6年前   427

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 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 ".\bin\Debug\netcoreapp2.1\test.dll"

这个方法有3个参数, 第一个参数-p指定了数据库的类型,第二个参数-c指定了连接字符串,第三个参数-a指定了包含迁移类的程序集路径。

注意:其实这里还有第四个参数command, 可选值为down/up, 如果不指定,默认是up, 即运行所有还未运行过的数据库迁移类。

方法执行后,效果和进程内执行器的效果一致。

基本概念

在展示了一个简单示例之后,我们接下来看一下Fluent Migrator中的一些基本概念。

迁移(Migrations)

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接口(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来做数据库迁移。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对AIDI的支持。


  • 上一条:
    解决正则表示式匹配($regex)引起的一次mongo数据库cpu占用率高的问题
    下一条:
    ASP.NET Core2读写InfluxDB时序数据库的方法教程
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 分库分表的目的、优缺点及具体实现方式介绍(0个评论)
    • DevDB - 在 VS 代码中直接访问数据库(0个评论)
    • 在ubuntu系统中实现mysql数据存储目录迁移流程步骤(0个评论)
    • 在mysql中使用存储过程批量新增测试数据流程步骤(0个评论)
    • php+mysql数据库批量根据条件快速更新、连表更新sql实现(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2017-06
    • 2017-08
    • 2017-09
    • 2017-10
    • 2017-11
    • 2018-01
    • 2018-05
    • 2018-10
    • 2018-11
    • 2020-02
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2020-07
    • 2020-08
    • 2020-09
    • 2021-02
    • 2021-04
    • 2021-07
    • 2021-08
    • 2021-11
    • 2021-12
    • 2022-02
    • 2022-03
    • 2022-05
    • 2022-06
    • 2022-07
    • 2022-08
    • 2022-09
    • 2022-10
    • 2022-11
    • 2022-12
    • 2023-01
    • 2023-03
    • 2023-04
    • 2023-05
    • 2023-07
    • 2023-08
    • 2023-10
    • 2023-11
    • 2023-12
    • 2024-01
    • 2024-03
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客