使用EF Core的Code First,在设计阶段,直接使用Database.EnsureCreated()
和EnsureDeleted()
可以快速删除、更新最新的数据结构 。由于没有什么数据,删除的风险非常低 。但是对于已经投入生产的数据库,这个方法就绝对不可行了 。
考虑以下场景:项目已经上线,一直使用本地测试数据库进行开发,本地已经增加和修改了较多数据库表结构,线上数据庞大且实时更新,现在测试完毕需要进行上线 。
如果需要更新生产数据库,我能想的有两种方法:
从一开始就使用Migration
从数据库开始设计的时候,就使用EF Migration,保证数据库能够与代码同步,不过操作的时候,需要极为小心,务必要检查生成的更新数据库代码,直接连接生产数据库,
需要注意的事项:
- 从一开始就使用
Migration
,任何时候都不要使用Context.Database.EnsureCreated或者EnsureDeleted语句 。 - 使用
Add-migration
之后,不要删除生成的Migration文件,这些文件记录了数据结构的变化历史 。 - 并不是所有的变化都能自动识别,比如“修改表列名称大小写”,这种情况很多时候生成的数据是执行删除然后再新建,和我们重命名的初衷相去甚远 。因此要特别检查migrationBuilder.Drop相关的页面 。
逆向数据库到模型首先需要数据库的数据结构逆向到模型,我们使用
Scaffold
就可以了,详细文档就可以查看这里,需要注意的是,我们的场景下,已经有修改好的DataContext与Model,在进行scaffold的过程中,一定要指定outputdir和context,不要和当前的文件冲突 。根据自己的喜好,选择是否采用-DataAnnotations,另外也可以使用-table指定需要修改的表,没有被指定的表,将保持原样 。默认EF Core会按照自己的命名规则重新命名,如果你想保留自己的套路,那么使用-UseDatabaseNames参数 。Add-Migration输出的模型我指定放在Models文件夹,原来的Models文件夹,我改成了Models1,并且更换了命名空间以保证项目现在能够正常编译 。
- 导出的模型与DbConext:Models.Models命名空间,Models文件夹
- 新模型与DbConext:Models命名空间,Models1文件夹接下来运行
Add-Migration
。
add-migration initialcreate -context exportedContext
【使用EF Core更新与修改生产数据库】这样会在Migrations文件夹下面生成一个snapshot和一个migration文件 。snapshot是当前数据库的跟踪,另外一个是运用update-database时系统会执行的操作 。里面有一个Up()
和一个Down()
方法,Up是执行更新时EF对数据库的操作,Down是回滚当前更改 。由于这是第一次执行add-migration,EF Core会认为数据库现在还是空的,因此两个方法都有大量的语句,我们删除所有create和drop相关的语句,我这边是全部删除了,只留下空方法 。应用迁移,同步前面准备工作已经到位了,这一步将直接操作数据库了 。使用
update-database
将当前的migration更新到数据库,由于我们现在的数据结构和生产数据库的数据结构一模一样,实际上我们不需要执行什么操作(删除了Up、Down内部的代码),执行Update-Database只是让EF Core将Models和生产数据库建立联系 。我理解只是添加修改模型内容将Models1中的文件覆盖Models中的文件,由于类型命名的差异,可能会提示一些错误,按照自己的习惯修改就好了 。接下来是循序渐进,一点点修改模型,并经常add-migration,观察生成的语句是否正常 。__EFMigrationsHistory
中的记录,以便EF Core后续追踪 。
经验总结扩展阅读
- 银碗发黑怎么清洗最亮
- 正确使用电热毯方法
- 二进制炸弹实验 BinaryBombs
- 分布式存储系统之Ceph集群RBD基础使用
- 床位使用率如何计算
- 快手没网信号怎么办
- 【nginx】使用 nginx 时,使用 sub_filter 注入 js 代码,例如 google analysis 等
- 含源码 手把手教你使用LabVIEW OpenCV dnn实现图像分类
- 怎么用qq定位一个人的位置
- 为什么手机使用一会儿就很烫