Migrations
深入研究Migrations
1、使用迁移脚本,可以对当前连接的数据库执行编号更高的迁移,这个操作叫做“向上迁移” (Up),也可以执行把数据库回退到旧的迁移,这个操作叫“向下迁移(Down)
2、除非有特殊需要,否则不要删除Migrations文件夹下的代码。
3、进一步分析Migrations下的代码。分析Up、Down等方法。查看Migration编号。4、查看数据库的_EFMigrationsHistory表: 记录当前数据库曾经应用过的迁移脚本,按顺序排列
示例:
程序结构
Person 类
PersonConfig
MyDbContext
主程序类
运行:
此时查看 Migrations下生成的文件
发现文件中有两个 方法 分别是 up 和 down
up 方法是创建过程 向上迁移
down 是向下迁移 up创建了表 ,会滚的话 就是删除表
此时若是增加一列
执行命令(在实际开发中,不能操作过于频繁)
此时,Migrations文件中,新增了一个脚本 up方法中的内容也发生了改变,是增加一列
(文件前面的编号内容也在增大)
此时的向下迁移 down 方法
则是删除该列
执行 Update-Database
查看数据库内容
查看EFMigrationsHistory
ProductVersion : EFCORE 版本
MigrationsId : 显示数据库都执行了哪些脚本
这个表 是由EFCORE 维护
若估计删除表中一行记录
然后执行update-database
出现报错信息
列重复。
数据库其他迁移命令
Migrations其他命令
1、Update-Database XXX把数据库回滚到XXX的状态,迁移脚本不动
2、Remove-migration删除最后一次的迁移脚本
3、Script-Migration
生成迁移SQL代码。有了Update-Database 为什么还要生成SOL脚本。
可以生成版本D到版本F的SOL脚本:Script-Migration D F
生成版本D到最新版本的SOL脚本: Script-Migration D
Update-Database XXX
示例:
删除数据库
执行 Update-Database
此时数据直接到 AddHeight 版本
使用 Update-Database xx 尝试还原到上一个版本
刷新数据库,发现还原成功
表中记录也减少一条
再次 执行 删除数据库操作。
此时需要达到 只执行到Init 状态,不执行到 add height
测试成功
Remove-migration
为了防止不小心 删除了 破环了前后关系,最好不要手动删除迁移脚本
而是使用 Removing 命令 删除最近一次记录
Script-Migration
此时在编辑器 中打开了一个sql文件
这样的目的 是在项目上线后,修改数据时,能更直观的看到如何修改得数据库 ,防止不小心的操作破坏生产环境
生成中间版本 到某个版本的迁移脚本
sql脚本
再把该代码 复制到数据库中运行
结果:
Script-Migration D 生成某个版本到最新版本的数据迁移记录
EFCORE 反向工程
反向工程
I、根据数据库表来反向生成实体类
2、Scaffold-DbContext ‘Server=.;Database=demol;Trusted_Connection=True;MultipleActiveResultSets=true’
Microsoft.EntityFrameworkCore.SqlServer
开发一个项目,但这个项目已经有了一些数据库。这个时候可以考虑使用反向工程
示例:
新建数据库
新建表
命令输入执行
此时项目中自动生成了 Dbcontext 和 Person 类
注意
1、生成的实体类可能不能满足项目的要求,可能需要手工修改或者增加配置。
2、再次运行反向工程工具,对文件所做的任何更改都将丢关
3、不建议把反向工具当成了日常开发工具使用,不建议DBFirst.
FECORE 底层如何操作数据库
Know How
1、为什么需要了解EF Core底层原理
框架是简化操作,不是让程序员变成傻瓜
EFCORE 底层就是靠 ADO.NETCORE来操作的
原理:
查看生成的SQL语句
1、SOL Server Profiler(收费版才有)查看SOLServer数据库当前执行的SQL语句。
查询窗口执行过的sql 语句 在SQL Server Perfiler 就能监控到
代码方式
2、var books = ctx.Books.Where(b =>b.Price > 10 b.Title.Contains(“张”));
EF Core把C#代码转换为SQL语句的框架
EFCORE 有哪些做不到的事情
Why
1、C#千变万化;SQL功能简单。存在合法的C#语句无法被翻译为SQL语句的情况
var books = ctx.Books.Where(b => IsOK(b.Title));
private static bool IsOK(string s)
{return s.Contains("张");
}
示例:
语句成功被翻译成为sql
修改代码
完全可以编译通过的合法sql 语句
报错,该Linq 表达式 无法被翻译为sql
sqlseverprofiler中也没有记录
通过代码查看EFCORE 生成的SQL
Why
不是有SQL Server Profiler了吗?
SQL Server Profiler 是查看服务器上所有的SQL 语句,多人操作。
方法1: 标准日志
public static readonly ILoggerFactory
MyLoggerFactory
= LoggerFactory.Create(builder => builder.AddConsole(););
optionsBuilder.UseLoggerFactory(MyLoggerFactory);
示例:
nuget 查找 logging console
编写代码
运行:
方法2:简单日志
optionsBuilder.LogTo(Console.WriteLine):
可以自己写代码过滤一些不需要的消息
示例:
运行结果:
只输出跟sql语句相关的东西
运行结果:
好处:可以看到更细节的东西,不用引入logging的框架
方法3: TOQUERYSTRING
1、上面两种方式无法直接得到一个操作的SQL语句,而且在操作很多的情况下,容易混乱。(需要精确查看自己想看的sql)
2、EF Core的Where方法返回的是IQueryable类型, DbSet也实现了IQueryable接口。 IQueryable有扩展方法ToQueryString0可以获得SQL
3、不需要真的执行查询才获取SOL语句:只能获取查询操作的。
示例:
运行:
【总结】
写测试性代码,用简单日志; 正式需要记录SQL给审核人员或者排查故障,用标准日志;开发阶段,从繁杂的查询操作中立即看到SQL,用ToQueryString()。