EntityFrameworkCore+CodeFirst:根据实体自动生成数据库(二) 程序包管理控制台迁移

news/2024/5/3 9:46:48/文章来源:https://www.cnblogs.com/fei686868/p/16639405.html

二、程序包管理控制台迁移

需要在DAL层引用包:Microsoft.EntityFrameworkCore.Tools

 

 

 

然后在控制台程序中也需要引用包:Microsoft.EntityFrameworkCore.Design

 

这样,就完成了需要的组件的引用了。

接下来打开程序包管理控制台,在vs中的“工具”中

 

 

 

 

 将默认项目切换为CodeFirst.DAL

 

接下来敲入命令:

Add-Migration MyCodeFirst
MyCodeFirst:为自定义,每次构建都不能重名。比如下次构建,可以是MyCodeFirst1

如下:

 

命令会显示构建成功,这时候在我们的DAL层中会多了一个Migrations目录,每次的迁移文件都会存在该目录中

 

 20220830065221_MyCodeFirst.cs  :是针对本次迁移生成的文件。每次迁移都会生成一个对应的迁移文件。里面有一个Up方法和一个Down方法,Up方法表示要执行的操作,Down方法相当于回滚,如果需要还原到上一个状态,就会执行Down方法。

MyDbContextModelSnapshot.cs :生成的配置文件。只会生成一次。

 

接下来就是执行这些文件来创建数据库,执行以下命令:

update-database MyCodeFirst  //指向上面自定义的名称,意思是执行那个文件

这样就生成了数据库结构了

 

 

 

比如下一次结构有修改,那就执行 

Add-Migration 新定义的名称
再执行 update-datebase 新定义的名称
即可。

在数据库中,我们会发现多了一个__EFMigrationsHistory,该表是自动生成的,记录迁移过程

 

该种方式与第一种方式好在于,对于数据结构的变化,可以每次都更新到数据库。

但在生产环境下,不太适用,我们无法在服务器上通过 VS的nuget控制台去执行update-datebase 命令。

 

=======================================

SQL脚本

除了用 Add-Migration 命令和update-database 结合之外,我们还可以将变更的结构生成sql进行核对,使用script-migration命令即可

script-migration:不指定版本,默认生成最新迁移版本的(全部)SQL脚本 
script-migration source target :source 是源版本,target 是目标版本,根据两个版本的结构差异而生成sql

 

首先,我们先使用 Add-Migration test1命令,生成迁移代码,然后再使用 script-migration 命令生成脚本

执行后,再vs中会弹出一个.sql的文件,如

 

 

我们可以人工核对脚本的正确性,再拿到远程服务器上去执行。

但有时候,我们是在本地多次改了结构,会多次进行本地数据结构迁移。这时候,更新到远程时,需要将本地新增加的sql文件按照生成的时间顺序,分别放到远程上去执行,不然结构就会不对。

幂等 SQL 脚本

上面生成的 SQL 脚本只能用于将架构从一个迁移更改为另一个迁移;你需要适当地应用脚本,并且仅应用于处于正确迁移状态的数据库。 EF Core 还支持生成幂等脚本,此类脚本将在内部检查已经应用哪些迁移(通过迁移历史记录表),并且只应用缺少的迁移。 如果不确知应用到数据库的最后一个迁移,或者需要部署到多个可能分别处于不同迁移的数据库,此类脚本非常有用。

使用的命令是:Script-Migration -Idempotent 

也可以使用dotnet命令

dotnet ef migrations script --idempotent

 

====================================================

 

假如我们已经了Add-Migration MyCodeFirst,但是在生产环境下,我们既然没办法在nuget上执行  update-datebase  命令,那么我们也可以用应用程序来执行
原理都是调用dbcontext上下文对象的.Database.Migrate() 方法来实现。

可以有两种使用方式,不同应用场景:

1:直接在startup.cs的Configure方法中直接调用,如

  var dbContext = app.ApplicationServices.GetRequiredService<MyDbContext>();dbContext.Database.Migrate();

这样也可以实现更新。

2:写扩展类来执行
代码放这里,看着感觉不太顺眼,不太合理对吧。

那就定义一个扩展类DatabaseManagementService

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using CodeFirst;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;namespace WebApplication1
{public static class DatabaseManagementService{// Getting the scope of our database contextpublic static IApplicationBuilder UseMigrationInitialisation(this IApplicationBuilder app,IWebHostEnvironment env,IConfiguration configuration){using (var serviceScope = app.ApplicationServices.CreateScope()){using (var context = serviceScope.ServiceProvider.GetService<MyDbContext>()){var db = context.Database;db.Migrate();SeedData(context, env, configuration); //创建数据种子}}return app;}private static void SeedData(MyDbContext _context,IWebHostEnvironment env,IConfiguration configuration){if (env.IsDevelopment()){//Do something for DEV 
            }else{//Do something for Production
            }if(!_context.Set<Student>().Any()) //若是空,则写入默认数据,避免重复写入{Student model = new Student();model.Name = "风扇";model.sex = 0;model.Age = 10;_context.Set<Student>().Add(model);}_context.SaveChanges();}}
}

 

然后在 startup.cs的路由终结点时,调用

  app.UseEndpoints(endpoints =>{endpoints.MapControllerRoute(name: "default",pattern: "{controller=Home}/{action=Index}/{id?}");}).UseMigrationInitialisation(env, Configuration);

 

通过这种方法,也可以达到目的,同时又能初始化一些数据。

但是,在程序端执行,有几个点需要特别注意:

  • 如果应用程序的多个实例正在运行,这两个应用程序可能会尝试同时应用迁移并失败(更糟糕的情况是导致数据损坏)。
  • 同样,如果一个应用程序正在访问数据库,而另一个应用程序正在迁移它,这可能会导致严重的问题。
  • 应用程序必须具有提升的访问权限才能修改数据库架构。 在生产环境中限制应用程序的数据库权限通常是一种很好的做法。
  • 出现问题时,能够回滚已应用的迁移很重要。 其他策略可以轻松提供此功能,并且开箱即用。
  • 程序会直接应用 SQL 命令,不给开发人员检查或修改的机会。 这在生产环境中可能会很危险。

也就是说,这个程序建议应该是独立的,专门给数据库迁移使用,而不是在业务程序中执行。

至此,程序包管理控制台迁移完成。

更多分享,请大家关注我的个人公众号:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_15729.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot统一异常处理详解

文章目录一、概述1、统一异常处理介绍2、原理和目标二、Assert(断言)1、概述2、Assert自定义实战2.1 自定义接口Assert2.2 自定义异常2.3 Enum整合2.4 实战检测三、统一异常处理器1、异常处理器说明1.1 handleServletException1.2 handleBindException和handleValidException1.…

35分钟了解sql注入-盲注(三)

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;学习sql注入之盲注操作 ✅创作者&#xff1a;贤鱼 ⏰预计时间&#xff1a;25分钟 &#x1f389;个人主页&#xff1a;贤鱼的个人主页 &#x1f525;专栏系列&#xff1a;网络安全 盲注布尔盲注原理布尔盲注payload构造步骤…

切面的优先级、基于XML的AOP实现

切面的优先级 相同目标方法上同时存在多个切面时&#xff0c;切面的优先级控制切面的内外嵌套顺序 1.优先级高的切面&#xff1a;外面 2.优先级低的切面&#xff1a;里面 使用Order注解可以控制切面的优先级 1.Order(较小的数)&#xff1a;优先级高 2.Order(较大的数)&#x…

MySQL(五)增删改查进阶

目录 一、数据排序 1、基础排序 2、过滤筛选 ​3、多字段排序 4、区间判断 5、嵌套/多条件 6、 查询不重复记录 二、分组 1、对结果进行分组 三、限制 1、限制输出的结果记录 四、设置别名 1、对于列的别名 2、对于表的别名 四、视图 1、视图和表区别 2、联系…

遇到一个bug,组件不更新内容

解决办法 当v-if的值发生变化时,组件都会被重新渲染一遍。因此,利用v-if指令的特性,可以达到强制刷新组件的目的。 <template><comp v-if="update"></comp><button @click="reload()">刷新test1组件</button> </templ…

Linux权限总结

放弃不难&#xff0c;但坚持很酷&#xff0c;加油&#xff01;希望此文对您有所帮助&#xff01; 目录 shell运行原理---外壳程序Linux权限的概念如何修改文件权限&#xff1f;常见权限问题&#xff08;面试题&#xff09;1.目录权限2.umask3.写权限的作用4.如何创建一个共享目…

机器学习在分子模拟中的应用

文章目录一、背景二、分子动力学模拟介绍简史基本步骤应用发展方向三、AlphaFold**前言****Alphafold2做了什么改进****Alphafold2会议具体细节&#xff1a;****Alphafold为什么强&#xff1f;****学术问题&#xff1a;**四、TorchMD五、Deep Potential**阶段一&#xff1a;对已…

TCP/IP网络编程:P3->地址族与数据序列

本系列文章为《TCP/IP网络编程----尹圣雨》学习笔记&#xff0c;前面的系列文章链接如下 TCP/IP网络编程&#xff1a;P1-&#xff1e;理解网络编程和套接字 TCP/IP网络编程&#xff1a;P2-&#xff1e;套接字类型与协议设置 文章目录前言一、分配给套接字的IP地址与端口号1.1 网…

CSP2022 J/S 游寄

9.18 A.m. 自己学校考,但只能睡到7点不到,就很无语。 来了好多同学,关系也不错,聊了一会天就去考试了。 至于考试没什么好说的,J也就那样。 P.m. 上午对了一下答案,貌似 \(92\) ? 中午机房太吵了,没怎么睡就去考试了。 考什么大家应该都有数,宇宙射线?秒表?做尼玛呢…

卷积神经网络的应用实例,卷积神经网络可解释性

神经网络激活函数与损失函数的作用 谷歌人工智能写作项目&#xff1a;神经网络伪原创 深度学习之损失函数与激活函数的选择 深度学习之损失函数与激活函数的选择在深度神经网络&#xff08;DNN&#xff09;反向传播算法(BP)中&#xff0c;我们对DNN的前向反向传播算法的使用做…

单片机原理与应用以及C51编程技术——硬件体系结构梳理

文章目录一、单片机的结构原理1.1 主要性能和特点1.2 内部框图1.3 CPU1.3.1 运算器1.3.2 控制器1.4 几个主要的特殊功能寄存器SFR说明1.4.1 程序指针PC1.4.2 累加器A1.4.3 寄存器B1.4.4 数据指针DPTR1.4.5 程序状态字PSW介绍例子1.4.6 堆栈指针SP堆栈的介绍堆栈的作用堆栈操作的…

Verilog学习笔记

sky视频笔记&#xff1a;数字逻辑回顾&Hello World_哔哩哔哩_bilibili 一、数电基础 1.组合逻辑 电路逻辑输出值只和当前的输入有关比如&#xff1a;AND/OR/XOR/NAND/NOR/MUX/Adder/Multiplier 2.时序逻辑 电路逻辑输出值跟当前的输入和电路的当前状态有关保存当前状态的…

用Python生成Hilbert矩阵

代码放在了最后&#xff0c;前面是解题思路 目录 1.什么是Hilbert矩阵矩阵&#xff1a; 2.找规律 1.第一种思路&#xff1a;先从值出发&#xff08;找规律&#xff09; 2.第二种思路&#xff1a;先从下标索引出发&#xff08;找规律&#xff09; 三、代码展示 四、输出展…

WPF 界面打不开提示 System.ArithmeticException Overflow or underflow in the arithmetic operation 异常

本文告诉大家如何解决界面打不开,抛出 System.ArithmeticException: Overflow or underflow in the arithmetic operation 异常的修复方法本文告诉大家如何解决界面打不开,抛出 System.ArithmeticException: Overflow or underflow in the arithmetic operation 异常的修复方…

某IOT设备漏洞分析

申明&#xff1a;本文章所分享内容仅用于网络安全技术讨论&#xff0c;切勿用于违法途径&#xff0c;所有渗透都需获取授权&#xff0c;违者后果自行承担&#xff0c;与本文及作者无关&#xff0c;请谨记守法. 设备名称: DLINK DIR-818l 固件包: d-link DIR818L_FW105b01 A1 环…

Rust学习笔记:简单练习

最近一个月比较闲&#xff0c;忙碌大半年终于有自己短暂的休息时间。如果不写大的程序&#xff0c;偶尔写写一些小东西&#xff0c;其实用起来也很自在&#xff0c;前提是如果没有太多生活压力。看电视变成奢侈的事情。有时候&#xff0c;我会羡慕老外享受福利待遇非常好&#…

javaweb|JSTL的下载、配置与原理,解决uri导入时报错的问题

今天在配置jstl时&#xff0c;发现在引入uri时出现了问题&#xff0c;地址直接报红。在尝试了几种方法后&#xff0c;最后成功解决了。 JSTL一、下载1、https://tomcat.apache.org/2、找到taglib标准库3、下载前2个jar包二、配置1、放入web-inf的lib文件夹里2、将Jar包放入tomc…

windows下 解决PHP-CGI 进程崩溃502

PHP是世界上最好的语言&#xff0c;但需要PHP解析器&#xff1b;Apachephp,需要通过mod_php.so和php相连&#xff1b;nginxphp 需要转发给 cgi程序 关于FastCGI&#xff1a; 全称 FastCGI Process Manager&#xff0c;是一种进程管理器&#xff0c;管理 cgi&#xff0c;市面上…

1474_AURIX TC275 WDT的运行模式

全部学习汇总&#xff1a; GreyZhang/g_TC275: happy hacking for TC275! (github.com) 1. 前面的内容中其实已经看到了&#xff0c;这个看门狗的时钟其实是固定的&#xff0c;SPB的时钟。这样&#xff0c;后面了解时钟树的时候需要注意一下。其实&#xff0c;在功能安全的失效…

ES6--》一文搞懂JS中的Promise

目录 Promise Promise使用 Promise封装Ajax请求 Promise封装读取文件 Promise.prototype.then 方法 Promise多文件读取 Promise.prototype.catch() Promise.prototype.finally() Promise.all() Promise.race() Promise.allSettled() Pomise.any() Promise.resolve…