Skip to content

数据库版本迁移

Jijie Chen edited this page Apr 17, 2019 · 5 revisions

数据库迁移分为开发时的声明和实际变更操作两部分。

声明数据库结构变更

要修改数据库结构时,请在 Discussion.Migrations 项目中,编写对应的迁移类完成新结构的声明。其步骤如下:

  1. 在项目根目录,创建一个以数字开头、下划线,以及数据库结构变更的简单介绍为名称的类
  2. 完成数据库变更类的编写,在类上标记 [Migration(version)] 特性,其中 version 是按顺序数下来的,请在当前的最大版本号之后开始增长
  3. 如果是创建一个新的实体类的表,那么继承自 CreateEntityTableMigration 类,并提供对应的表名和除 Id 之外的所有列的信息;
  4. 如果是对已有的数据表进行操作,或者是进行其他操作,并继承自 Migration 类,在 Up 方法中添加对数据库的操作,在 Down 方法中添加逆向的操作。

关于 Up 方法的写法,请参考 FluentMigrator 的文档。为了保持多数据库的兼容性,请尽量使用 FluentMigrator 提供的 API 完成数据库变更,而不要使用 Execute.Sql 的原生 SQL。

有些操作无法被逆向恢复(比如,删除列的操作,无法被撤回),请在对应的 Down 方法中保留默认的 throw new NotImplementedException(); 实现。

除非完全没有损害,或者必须要修改的情况,原则上所有数据库迁移类一经推送到远端代码库,就不能再进行修改。如果要修改,则应该写一个新的数据库迁移类纠正之前的错误。

不支持删除列

目前 dotnetclub 还在使用 Sqlite 作为数据库,而 FluentMigrator 的 Sqlite 驱动程序还不支持执行从已创建的表上删除现有列。因此,如果需要删除列,则请执行下列操作:

  1. 在原来创建表的迁移类上,删除对此次要删除的列的声明(虽然这违反了不应该更改已经编写的迁移类,但如果不这样做,很有可能由于 C# 代码不再向该列写入值、而列却要求非空,最终导致错)
  2. 如果你一直本地开发环境持续维护了自己的数据库文件,则使用数据库管理工具打开数据库文件,并手动删除这些列
  3. 将要删除这些列这一信息,以另外的渠道(如提一个 GitHub Issue)通知 Repo Owner,从而支持在下次部署期间手动将线上数据库中这些列删除

有计划将数据库从 Sqlite 更换为其他数据库,比如 PostgreSQL,欢迎讨论和 PR。

变更数据库结构

在开发环境中,如果需要持续维护数据库,则会需要手动对已有的数据库文件执行迁移。

操作步骤如下:

  1. 切换到 src/Discussion.Migrations 项目目录
  2. 完成编译 dotnet build
  3. 使用下面的命令执行迁移:
dotnet run 'Data Source=../Discussion.Web/dotnetclub.db'

注意引号中的参数:

  • 它是一个完整的 Sqlite 连接字符串
  • 其中包含的数据库路径可以是相对路径,也可以是绝对路径。当是相对路径时,相对的是运行命令行的“当前工作目录”。