[转载] EF Core migration分析
NETCore的数据库迁移主要分二个步骤
- 生成迁移文件
- 数据库迁移
具体命令我们不讨论,我们只讨论最基本的2个命令后面做了什么,以及我们可能碰到的问题。
0. 前言
整个迁移过程涉及到三个基本概念,我们先明确一下:
* 数据库:比如mysql下某个具体的数据库实例
* 源码:项目的源码,包括一个或多个DBContext
* 迁移文件:缺省在项目源码根目录下的migrations目录下,包含迁移增量文件和镜像文件
其中第一个步骤需要用到源码生成迁移文件,第二个步骤根据迁移文件更新数据库
1. 生成迁移文件
dotnet ef migrations add mirgation1 -v
加上-v参数可以看到执行的详细过程,这个过程涉及到上面提到的三个基本概念,同时整个过程也包含了三部分:
1.1 执行dotnet build 编译整个源码,源码必须保证编译没有错误才能迁移(废话)。
1.2 执行编译后的dll,并不是dotnet run,而是dotnet exec。所以源码必须执行没有问题,这个不是废话,因为我们有的时候运行项目是带参数的,带参数能运行,并不能表示不带参数运行不出错。
另外这个步骤同时会去查找所有继承了DbContext的类,如果有多个类,会提示执行失败需要加上-context参数。
注意,mirgations add是不需要用到数据库的,但是执行dll可能会需要连接上数据库,但是这个数据库可以不是最终真正的数据库,一个临时测试的数据库也可以。
dotnet exec --depsfile C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.deps.json --additionalprobingpath C:\Users\liuyi\.nuget\packages --additionalprobingpath "C:\Program Files\dotnet\sdk\NuGetFallbackFolder" --runtimeconfig C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.runtimeconfig.json "C:\Program Files\dotnet\sdk\2.1.400\DotnetTools\dotnet-ef\2.1.1\tools\netcoreapp2.1\any\tools\netcoreapp2.0\any\ef.dll" migrations add mirgation1 --assembly C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll --startup-assembly C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample\bin\Debug\netcoreapp2.0\MigrationsSample.dll --project-dir C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample\ --language C# --working-dir C:\Work\Github\jianshu_sample\MigrationsSample\MigrationsSample --verbose --root-namespace MigrationsSample
1.3 结束上个步骤的执行,生成或修改镜像文件和增量文件。
这里经常碰到一个问题,执行上面的步骤1.2的时候没法结束,导致整个迁移卡死,原因是执行1.2的时候有可能会启动一个死循环的前台线程,导致进程没法正常结束。
image.png
这个过程搜索DBContext类下所有的DBSet以及对应的所有字段,然后和镜像文件比较,如果镜像文件不存在,则生成一个并把所有的表和字段都添加上,如果存在,则比较现有源码里的表结构和镜像文件的表结构的差异,把差异转换成增量文件,并更新镜像文件。
所以执行migrations add的时候,实际上是,所以镜像文件就可以理解是数据库完整表结构的c#实现(如上图DataContextModelSnapshot.cs)。
而增量文件就是一堆AddColum,DropColumn,CreateTable,RemoveTable等函数,表示这次变化是添加了新字段,删除新字段等等增量操作。
2. 数据库更新
dotnet ef database update -v
根据上面步骤1生成的增量文件更新数据库。也分三个步骤:
2.1 编译项目,和1.1一样
2.2 运行项目,和1.2一样
2.3 在数据库里查找_efmigrationshistory表里的记录
image.png
根据里面的MigrationId到当前的所有迁移增量文件里找,如果有对应的增量文件,则忽略,把没有在这个表里的所有增量文件执行一遍,通过AddColum,DropColumn,CreateTable,RemoveTable等函数来更新数据库。 所以这个步骤实际上是,我们2.1步骤是需要编译项目源码的,其实我们可以跳过2.1步骤