使用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
这样会在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后续追踪 。
由于我使用了
Identity
,在数据中有对应的AspNet
开头的表 , 这些表我并不在本系统中使用(其他系统需要用),因此我删除了对应的模型、snapshot、DbContext记录,运行Add-Migration,生成了如下文件:protected override void Up(MigrationBuilder migrationBuilder){migrationBuilder.DropTable(name: "AspNetRoleClaim");migrationBuilder.DropTable(name: "AspNetUserClaim");migrationBuilder.DropTable(name: "AspNetUserLogin");migrationBuilder.DropTable(name: "AspNetUserRoles");migrationBuilder.DropTable(name: "AspNetUserToken");migrationBuilder.DropTable(name: "AspNetRole");migrationBuilder.DropTable(name: "AspNetUser");}
说明现在已经能够正常跟踪我们的修改了,不过我这里需要保留对应的表,因此删除up与down的所有内容 。
推荐阅读
- 分布式存储系统之Ceph集群RBD基础使用
- 【nginx】使用 nginx 时,使用 sub_filter 注入 js 代码,例如 google analysis 等
- 含源码 手把手教你使用LabVIEW OpenCV dnn实现图像分类
- 利用Pandas处理数据 缺失值的处理 数据库的使用 python-数据描述与分析2
- 18 基于.NetCore开发博客项目 StarBlog - 实现本地Typora文章打包上传
- vue3中pinia的使用总结
- HBase1.4.6安装搭建及shell命令使用
- 长江雨课堂app怎么签到
- 如何使用 Yolov4 训练人脸口罩检测模型
- 用 VS Code 搞Qt6:使用 PySide 6