.net core Code First不太常用功能
>简单说明快速搭建.net core api项目依次新建项目添加数据库模型配置连接数据库迁移模型到数据从属实体类型-Owned添加Address属性添加迁移/修改数据库指定保留小数点位数生成数据库sql语句生成初始状态到版本F的迁移脚本生成版本D到版本F的迁移脚本
简单说明
.net core 6.0
Microsoft.EntityFrameworkCore 6.0.15
Pomelo.EntityFrameworkCore.MySql 6.0.2
Microsoft.EntityFrameworkCore.Tools 6.0.2

快速搭建.net core api项目
应该搞个脚手架的,不然每次都要点来点去。目前比较主流的是新增 Migration(类库)项目来专门管理代码迁移变动,将DBContext放在DataAccess(类库、仓储)项目中,方便后期维护管理。这里就随便搞得简单点。
依次新建项目
MyDemo.Entities(类库)
MyDemo.Host(.net core api项目)
添加数据库模型
MyDemo.Entities项目 新增Models文件夹、在该文件夹下新建模型User.cs
public class User { public Guid Id { get; set; } public string Name { get; set; } public int Age { get; set; } }建好模型后,新建 MyDemoDbContext.cs
安装 Microsoft.EntityFrameworkCore 包,注意版本
xpublic class MyDemoDbContext:DbContext{ public MyDemoDbContext(DbContextOptions options) : base(options) {
} public DbSet<User> Users { get; set; }}配置连接数据库
MyDemo.Host项目 在Program.cs配置数据库链接,注意service和build的位置顺序
安装 Pomelo.EntityFrameworkCore.MySql 包,注意版本
xxxxxxxxxxvar services = builder.Services;var connection = "server=127.0.0.1;user=root;pwd=123456;database=mydemo";services.AddDbContextPool<MyDemoDbContext>(options => options.UseMySql(connection, ServerVersion.Parse("8.0"), b => b.MigrationsAssembly("MyDemo.Host")));
// var app = builder.Build(); // Build()后不能再配置service了,所以要将数据库相关配置写在build前,卡了我一下午了// ...迁移模型到数据
MyDemo.Host项目安装 Microsoft.EntityFrameworkCore.Tools 包,注意版本
打开程序包控制台:顶部[工具]菜单项->Nuget包管理器->程序包管理控制台
控制台项目的默认项目和解决方案的启动项目都选MyDemo.Host项目

添加迁移/修改数据库
xxxxxxxxxxadd-migration add-table-userupdate-database
从属实体类型-Owned
[Owned] 特性可以从另一个实体类型引用时将其视为从属实体,即将某个类的所有属性作为其引用类的属性
如User有Address的信息,我们可以使用关联关系做映射也可以直接将Address的信息放在User表中
添加Address属性
xxxxxxxxxx public class User { public Guid Id { get; set; } public string Name { get; set; } public int Age { get; set; } public Address? Address { get; set; } }
[Owned] public class Address { public string Country { get; set; } public string State { get; set; } public string City { get; set; } public string Detail { get; set; } }---2023/11/10补充--- 值得注意,.net 6.0版本之前,EF Update更新数据库操作默认不会更改Owned实体的字段,需要我们手动处理。这属于已知bug,.net 6.0+版本后已修复,无需手动处理。
如我们在.net 6.0版本之前需要更新Owned实体的字段,我们需要手动将 Owned 实体内部的属性启用编辑
xxxxxxxxxx var entry = Context.Attach<User>(entity); var ownEntry = entry.Reference("Address"); // 引用 Owned 属性对象,这里是属性名称,不是类名 if (ownEntry.TargetEntry == null) return; // Owned 实体内部的属性启用编辑 ownEntry.TargetEntry.Property("Country").IsModified = true; // 属性名称 ownEntry.TargetEntry.Property("State").IsModified = true; ownEntry.TargetEntry.Property("City").IsModified = true; ownEntry.TargetEntry.Property("Detail").IsModified = true; Context.Update(entity); // 执行更新操作添加迁移/修改数据库
xxxxxxxxxxadd-migration add-user-column-addressupdate-database通过desc Users 查看表结构,我们可以看到Address的属性是作为User的属性存在于User表中的

指定保留小数点位数
一般默认情况下,通过Code First迁移模型生成数据库,sql server的小数点是两位,mysql则是30位,若要指定保留小数点位数则只需要再每次添加迁移后修改Up方法内的type即可

每次添加迁移都要手动修改代码会比较麻烦,而且也不建议如此操作。建议重写DBContext的OnModelCreating方法,在该方法内进行配置即可
xxxxxxxxxx protected override void OnModelCreating(ModelBuilder modelBuilder) { // 可以单独指定某个字段 modelBuilder.Entity<User>().Property(x => x.Money).HasPrecision(18, 4); // 但不支持Owned的从属属性 // modelBuilder.Entity<User>().Property(x => x.Address.Price).HasPrecision(18, 4); // modelBuilder.Entity<Address>().Property(x=>x.Price).HasPrecision(18, 4); // modelBuilder.Entity<Address>().Property(x=>x.Price).HasPrecision(18, 4);
// 也可以指定全部decimal或decimal?类型的字段,同时支持Owned的从属属性,若多次指定则覆盖 foreach (var entityType in modelBuilder.Model.GetEntityTypes()) { foreach (var propertyInfo in entityType.ClrType.GetProperties()) { if (propertyInfo.PropertyType == typeof(decimal) || propertyInfo.PropertyType == typeof(decimal?)) { var property = entityType.FindProperty(propertyInfo); if (property == null) continue; property.SetPrecision(16); property.SetScale(5); } } }
base.OnModelCreating(modelBuilder); }我们再看执行添加迁移后生成的代码,一开始我们指定保留4位小数,后面又统一将decimal、decimal? 类型的字段指定保留5位小数

生成数据库sql语句
生成迁移SQL语句,主要用于开发完成后生成脚本,将脚本放到生产环境中执行。如新版本新增某些功能需要修改数据库表,这时我们可以通过 script-migration 快速查出数据库修改了哪些地方——新增、删除字段,新增、删除表等等
语法:生成版本D到版本F的SQL脚本,注意不包含版本D的脚本
script-migration -From D -To F -o xxx.sql
生成初始状态到版本F的迁移脚本
-FROM 参数为0时,表示生成初始状态到版本F的迁移SQL,包含版本F之前的所有变动
xxxxxxxxxxscript-migration -FROM '0' -To 20230412022011_add-user-column-address -o MyDemo.Host/Script/01-add-user.sql
生成版本D到版本F的迁移脚本
-FROM、-TO可省略;
前者为From、后者为To;
FROM必填、TO选填,不填则表示迁移至最新的版本;
不包含FROM、包含TO的脚本变化;
xxxxxxxxxxscript-migration 20230412022011_add-user-column-address 20230412030112_update-user-column-money -o MyDemo.Host/Script/02-update-column-money.sql