如何使用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 ".\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来做数据库迁移。
如何使用FluentMigrator进行数据库迁移的更多相关文章
- 使用FluentMigrator进行数据库迁移
介绍 在开发的过程中,经常会遇到数据库结构变动(表新增.删除,表列新增.修改.删除等).开发环境.测试环境.正式环境都要记性同步:如果你使用EF有自动迁移的功能,还是挺方便的.如果非EF我们需要手工处 ...
- 数据库迁移 Migrator.Net
转载: [强烈推荐]数据库迁移利器:Migrator.Net Migrator.NET:https://github.com/migratordotnet/Migrator.NET fluentmig ...
- EF Code First Migrations数据库迁移
1.EF Code First创建数据库 新建控制台应用程序Portal,通过程序包管理器控制台添加EntityFramework. 在程序包管理器控制台中执行以下语句,安装EntityFramewo ...
- 2.EF中 Code-First 方式的数据库迁移
原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/code-first-migrations-with-entity-framework/ 系列目 ...
- laravel数据库迁移(三)
laravel号称世界上最好的框架,数据库迁移算上一个,在这里先简单入个门: laravel很强大,它把表中的操作写成了migrations迁移文件,然后可以直接通过迁移文件来操作表.所以 , 数据迁 ...
- Code First开发系列之数据库迁移
返回<8天掌握EF的Code First开发>总目录 本篇目录 开启并运行迁移 使用迁移API 应用迁移 给已存在的数据库添加迁移 EF的其他功能 本章小结 自我测试 本系列的源码本人已托 ...
- ABP Migration(数据库迁移)
今天准备说说EntityFramework 6.0+,它与我之前所学的4.0有所区别,自从4.1发布以来,code first 被许多人所钟爱,Dbcontext API也由此时而生.早在学校的时候就 ...
- sqlserver 2008R2数据库迁移oracle
x项目需要,将以前的sqlserver数据库迁移的oracle数据库中,由于以前对oracle只是在DML语句的步骤,所以总结一下这次遇到的问题以及具体步骤 1,oracle新建数据库 新建Oracl ...
- 【强烈推荐】数据库迁移利器:Migrator.Net
简介 很郁闷,写了一天的遇到LiveWriter错误,可恶啊 几年前在做项目中第一次接触到了Migrator.Net,就深深被吸引住了,至此以后在新的大项目中,我都会使用Migrator.Net来创建 ...
随机推荐
- python笔记:#004#注释
注释 目标 注释的作用 单行注释(行注释) 多行注释(块注释) 01. 注释的作用 使用用自己熟悉的语言,在程序中对某些代码进行标注说明,增强程序的可读性 02. 单行注释(行注释) 以 # 开头,# ...
- Python黑客泰斗利用aircrack-ng破解 wifi 密码,超详细教程!
开始前,先连上无线网卡,因为虚拟机中的kali系统不用调用笔记本自带的无线网卡,所以需要一个外接无线网卡,然后接入kali系统. 输入 ifconfig -a 查看网卡,多了个 wlan0,说明网卡已 ...
- HTML知识点总结
HTML知识点总结 一.需要熟悉的基本快捷键 ctrl+c 复制 ctrl+v 粘贴 ctrl+x 剪切 ctrl+tab ...
- 虚拟机配置Openstack常见问题汇总
之前配置了openstack,遇到一些问题,现在将问题全部汇总记录在这里. (1)问题:主机名字修改不了: 原因:没有进入root状态:或者没有正确打开文件,要打开的是/etc/hostname,结果 ...
- 在线引用js资源积累
[jQuery]https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js[Vue]https://cdnjs.cloudfla ...
- React入门一
React.js算是当今主流框架之一了,好多公司项目都是React.直接上图: 所以最近整合一些论坛,今儿咱就说说React, React 是一个用于构建用户界面的 JAVASCRIPT 库. Rea ...
- thymeleaf 货币格式化 数字格式化问题
格式化数字对象 ${'¥'+#numbers.formatDecimal(pro.price,0,'COMMA',2,'POINT')} ${'¥'+#numbers.formatDecimal(pr ...
- PAT1126:Eulerian Path
1126. Eulerian Path (25) 时间限制 300 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue In grap ...
- sniffer pro 使用方法
一.捕获数据包前的准备工作 在默认情况下,sniffer将捕获其接入碰撞域中流经的所有数据包,但在某些场景下,有些数据包可能不是我们所需要的,为了快速定位网络问题所在,有必要对所要捕获的数据包作过滤. ...
- 一个很有趣的示例Spring Boot项目,使用Giraphe CMS和Spring Boot
6: 这是一个很有趣的示例Spring Boot项目,使用Giraphe CMS和Spring Boot. Giraphe是基于Spring Boot的CMS框架. https://github.co ...