看见过几篇其他大神写的关于EFCore2.0的文章。本人有点小白,一开始看文档的时候除了一些基本操作外其他部分几乎没有读懂,我估计会有一部分人跟我一样,因为人家读懂了的早就懂了。
在这里我写一下我自己的理解和观点,并基于EF6的机制做一些比较。理解可能比较表象,如果有错误希望大神们指正。
一、迁移指令
从EF6的经验来讲,建立完基类,接口,表和一堆服务后我们,在模型初始化方法里添加迁移模式的配置然后,直接在控制台执行Enable-Migrations就可以了。
但是在EFCore2.0中我执行启动自动迁移,得到下面这个
Enable-Migrations is obsolete. Use Add-Migration to start using Migrations.
简单来说就是,Enable-Migrations过期了,让你用Add-Migration。
经过了一番百度得到的诸多的文章一般都是说,在控制台执行Add-Migration和Update-Database两个指令。参考 EF Core 数据库迁移(Migration)
先说下 Add-Migration 的基本用法, Add-Migration { 迁移名称 } -Context {上下文名称}
迁移名称:我理解为迁移的版本号或版本说明一类的东西
上下文名称:当项目中存在多个继承DBContext的类的时候需要指定上下文
还有其他的参数这里就先不说了。
执行 Add-Migration Update 等指令运行完,会发现项目下多了一个Migrations文件夹
一般来讲会有三个文件(名字都是我自己起的)
- 变更文件:时间戳_迁移名称.cs
- 结构快照:时间戳_迁移名称.Designer.cs
- 当前快照:上下文名称ModelSnapshot.cs
一般来讲变更文件和结构快照是配套出现的,而当前快照只有1个。随着执行迁移的次数的增加,文件数量也会越来越多。
变更文件,是EF根据当前的模型和已有的最新的快照生成变更方法文件
这里会涉及到两个方法,Up和Down。
Up是更新数据库的操作图上显示的就是一个创建表。
Down方法是回滚操作,也就是当你发现这次更新有问题的时候,回滚数据库版本(仅结构)用的。
结构快照,EF根据当前的模型生成的数据库结构文件,这个不用去管。
当前快照,会指向当前EF所运行的数据库迁移版本的快照,以这个为基准与数据库沟通,默认指向最新的结构快照。
二、CodeFirst迁移数据库
上面提到过了Enable-Migrations指令不好使了,那我们在添加迁移版本(Add-Migration)以后还要执行一下Update-Database。这个指令没啥好说的,直接执行就好。
执行完命令,我们会发现数据库建好了。
但是我认为这个方法非常的不方便,也不科学,为什么呢?
试想一下,我们的开发环境肯定与运行环境不是在一起的,更不可能用同一个数据库。那么我用IDE来跟新了开发用的数据库没问题,发布完跟部署工程师说:“你要在服务器上通过命令执行一个XXX命令才能建立或更新数据库”。这个不太可能!估计说完了,你部署的同事就疯了。
所幸在DBContext中发现了一个Database对象
它具有一个Migrate方法,可以来启动EF的数据库更新方法。
那我们可以修改数据库上下文的构造方法
public class ApplicationDb : DbContext
{ public ApplicationDb(DbContextOptions<ApplicationDb> options) : base(options)
{
if (!Database.EnsureCreated()) //确认数据库是否被建立
{
Database.Migrate();//启动迁移比对
}
} }
先检测数据库是否存在,如果不存在,则直接建立数据库,不进行迁移比对。存在的话,启动比对。根据官方文档,建立后不推荐执行Migrate方法以防冲突。
这样在项目启动的时候就会自动比对迁移,并更新数据库结构。
当然!这个代码仅用作示例!因为每次对创建DBContext兑现都去比对上下问,是对数据库一种无意义的重复开销,具体怎么封装,仁者见仁智者见智。
我的解决方案是做一个一异步的方法,在项目的Startup中的Configure中执行,达到项目启动时执行的效果。
三、EFCore2.0 与EF6迁移机制上的区别
EF都会在数据库里生成一个以前版本的表
EF6叫__MigrationHistory
EFCore2.0叫__EFMigrationsHistory
这两个文件都会存储迁移版本的名称,只不过EF6是自动生成的,EFCore2.0是要手动生成的。然后最关键的是Model字段。这个就是我们所谓的数据库快照。
EF6中每次启动的时候会根据当前模型生成一个模型快照,然后与数据库中最新的快照进行比对,如果产生差异,根据差异变更数据库。
但是在Core中并没有保存数据库快照,而是以代码的形式来保存。这就是为什么我们随着执行迁移的次数的增加,文件数量也会越来越多。那些文件都是数据库的快照。而数据库的本身只存储指向版本。
所以跟EF6一样,我们为了减少快照所占控件,可以删除除最新以外的快照文件(只要你不想回滚)。
四、关于迁移需要注意
本来我是打算做一个批处理文件,注册在在项目编译前,在项目编译的时候自动生成迁移。但是目前EFCore2.0的迁移功能还不够智能。
因为在你对字段重命名以后默认是删除字段,然后重建字段,而不是重命名字段。这点在EF6中做的还算不错。
所以需要开发者在添加迁移以后,去检查一下Up方法的操作是否是我们想要的。当然如果你需要用到回滚那还要检查一下Down方法。
这个希望能在以后的版本中得到改善吧。