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

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

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

(0)

相关推荐

  • asp.net mvc CodeFirst模式数据库迁移步骤详解

    利用Code First模式构建好基本的类后,项目也开始搭建完毕并成功运行,而且已经将数据库表结构自动生成了. 但是,我有新的类要加入,有字段需要修改,那怎么办呢,删库,跑路 ? 哈哈 利用数据库迁移,将原有结构不改动,将新建类进行单独建表操作,或者是已有数据库表,改变字段,那就修改表. 迁移步骤: 1.打开程序包管理器控制台:工具->NuGet包管理器->程序包管理器控制台.(当然还有其它方式也可以打开,我比较喜欢这种) 点击后将弹出程序包管理器控制台 极其要注意的是默认项目!!! 2.启动

  • 在.NET Core类库中使用EF Core迁移数据库到SQL Server的方法

    前言 如果大家刚使用EntityFramework Core作为ORM框架的话,想必都会遇到数据库迁移的一些问题. 起初我是在ASP.NET Core的Web项目中进行的,但后来发现放在此处并不是很合理,一些关于数据库的迁移,比如新增表,字段,修改字段类型等等,不应该和最上层的Web项目所关联,数据的迁移文件放到这里也感觉有点多余,有点乱乱的感觉,所以才想着单独出来由专门的项目进行管理会比较好,也比较清晰! 注意目标框架选择的是.NET Core 2.0而不是.NET Standard 2.0.

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

    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多的多,且

  • sql server2008数据库迁移的两种方法

    sql server2008数据库迁移的两种方法,具体内容如下 方案一 1.先将源服务器上的数据库文件打包(包括mdf和ldf文件),并且复制到目标服务器上. 2.解压,然后在目标服务器上附加数据库 总结:适合数据库巨大(50GB以上),需要快速迁移数据,并且移动硬盘空间足够大. 方案二:先备份后还原 1.备份 数据库对象右键\任务\备份 注意,如果数据库文件较大的话,最好选择'压缩备份' 2.还原 将备份文件copy到目标服务器上,然后还原数据库. 总结:适合数据库中小型(否则备份的时间比较长

  • Flask数据库迁移简单介绍

    前言 用过Django的小伙伴都知道,Django的ORM是自带的,比较特殊,而且集成了很多功能,比如数据库迁移- 何为ORM,个人之见解,简化sql语句的书写,将关系型数据库的一张张表转化为了python的类,最大的好处是简化了学习成本,不会sql语句的程序员也能平滑的使用数据库,并且天生防sql注入.flask可以使用SQLAlchemy,包名为flask-sqlalchemy.至于具体用法翻译的官方文档讲的也足够清楚.大家直接谷歌跟着文档就能搞定,本篇主要讲如何进行数据库迁移. flask

  • oracle数据库迁移到MySQL的方法总结

    前言 之前搭建了一个ExtJS + spring + Oracle 的这样一个报表系统的框架. 因为其他部门的要求, 也需要这个Framework 进行一些特殊的定制. 但是有一个问题是 Oracle 的数据库是需要收费的, 个人使用倒没什么问题, 公司使用的话就会有侵权的问题了. 而MySQL 则是完全免费的. 所以使用 ExtJS + Spring + MySQL  这样的组合应该就没什么问题了. 理论上来说, MySQL 已经被Oracle 收购, 这两者之间的Migrate 应该比较容易

  • 将ACCESS数据库迁移到SQLSERVER数据库两种方法(图文详解)

    ACCESS2000文件 用ACCESS2007打开,并迁移到SQLSERVER2005里 打开ACCESS2007的数据库工具 方法一:使用ACCESS2007自带的数据库迁移工具 1.打开ACCESS2007的数据库迁移向导 2.点击SQLSERVER按钮,弹出升迁向导对话框 3.选择新建数据库 4.输入计算机名,我的本地计算机名字叫joe,因为SQLSERVER安装在本地,所以选择使用可信连接就可以了 数据库名称默认就可以了 5.选择所有表,移动到右边框 6.把表索引也一起升迁到SQLSE

  • yii2.0数据库迁移教程【多个数据库同时同步数据】

    本文讲述了yii2.0数据库迁移的方法.分享给大家供大家参考,具体如下: 创建迁移 使用如下命令来创建一个新的迁移: yii migrate/create <name> 必填参数 name 的作用是对新的迁移做一个简要的描述.例如,如果这个迁移是用来往多个数据库同一张表  ( 假设每个数据库都有news表 )   添加字段的,那么你可以使用addColumn_news (该名称自定义)这个名称并运行如下命令: yii migrate/create addColumn_news 注意:因为 na

  • Laravel 5框架学习之数据库迁移(Migrations)

    database migrations 是laravel最强大的功能之一.数据库迁移可以理解为数据库的版本控制器. 在 database/migrations 目录中包含两个迁移文件,一个建立用户表,一个用于用户密码重置. 在迁移文件中,up 方法用于创建数据表,down方法用于回滚,也就是删除数据表. 执行数据库迁移 复制代码 代码如下: php artisan migrate #输出 Migration table created successfully. Migrated: 2014_1

  • mysql 通过拷贝数据文件的方式进行数据库迁移实例

    mysql通过拷贝数据文件的方式进行数据库迁移 --环境windows 将源机器A数据库拷贝到目标机器B: 我先在目标机器B上安装MySQL,停止mysql服务,然后将源机器A的data下关于数据库的文件和ibdata1拷贝过去,其余不用拷贝.如图: 源机器A: 启动目标数据库服务net start mysql,即可查看到导过来的所有数据库了. 注意:ibdata1一定不要忘记拷贝,且要拷贝到准确的位置(如我目标机器的ibdata1在E:\MySQL Datafiles,不在data路径下,我就

  • 利用PHP访问数据库_实现分页功能与多条件查询功能的示例

    1.实现分页功能 <body> <table width="100%" border="1"> <thead> <tr> <th>代号</th> <th>名称</th> <th>价格</th> </tr> </thead> <tbody> <?php require_once "./DBDA.cl

随机推荐