在EF中,有几种开发方式DBFrist,CodeFirst,ModelFirst,CodeFirsrtFromDB
但在EFCore中,一般用CodeFirst
EF中当我们要修改数据表结构时,我们要自己去数据库更改表结构,而如果生成sql的语句是直接删除全部表,再生成全部表,这必定会造成数据的丢失
所以才会有EFCore的迁移功能的诞生
EFCore的迁移功能可以自动生成升级脚本,只要修改模型,再创建迁移更新数据库即可
安装几个包
Microsoft.EntityFrameworkCore.Tools
Microsoft.EntityFrameworkCore.Design
Microsoft.EntityFrameworkCore.Migrations
命令
创建迁移 add-migration migrationname
移除迁移 remove-migration
应用最新的迁移 update-database
应用指定的迁移 update-database migrationname
模型
先创建用户模型
public class UserInfo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
创建上下文
public class EFCoreMigrationContext : DbContext
{
private string ConnectionString = "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreMigrationTest;Trusted_Connection=True;";
public DbSet<UserInfo> UserInfo { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionString);
}
}
在工具--NuGet包管理器--打开程序包管理控制台
执行 add-migration Init01命令
项目自动生成迁移文件
执行update-database命令
生成数据库
在模型字段发生变化时,使用add-migration migrationname添加迁移记录
再使用update-database 更新数据库
现在如果更改UserInfo的字段Name改为Name2,生成迁移文件
再将Name2改为Name,再创建模型中也可以添加初始化数据
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<UserInfo>().HasData(new UserInfo()
{
Id = 1,
Name = "haha",
Age = 18
});
}
对比3个迁移文件,发现迁移文件都是依赖上一个迁移文件的
表之间的对应关系
一般的关系有一对一,一对多,多对多
在OnModelCreating中创建表关系
各个模型
public class UserInfo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
public virtual UserInfoExt UserInfoExt { get; set; }
public virtual List<OrderInfo> OrderInfo { get; set; }
public virtual List<UserRoleMapping> UserRoleMapping { get; set; }
}
public class UserInfoExt
{
[Key]
public int Id { get; set; }
public int UserInfoId { get; set; }
public string Sign { get; set; }
public virtual UserInfo UserInfo { get; set; }
}
public class OrderInfo
{
[Key]
public int Id { get; set; }
public int UserInfoId { get; set; }
public string Content { get; set; }
public virtual UserInfo UserInfo { get; set; }
}
public class RoleInfo
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual List<UserRoleMapping> UserRoleMapping { get; set; }
}
public class UserRoleMapping
{
public int UserInfoId { get; set; }
public int RoleInfoId { get; set; }
public UserInfo UserInfo { get; set; }
public RoleInfo RoleInfo { get; set; }
}
其中
用户信息表与用户额外信息表是一对一的关系
用户信息表与订单信息表是一对多的关系
用户信息表与角色信息表是多对多的关系
我们可以配置日志输出到控制台,查看执行的sql
安装两个包
Microsoft.Extensions.Logging
Microsoft.Extensions.Logging.Console
public class EFCoreMigrationContext : DbContext
{
public static readonly ILoggerFactory MyLoggerFactory
= LoggerFactory.Create(builder => builder.AddConsole());
private string ConnectionString = "Server=GREAMBWANG-DC\\MSSQLSERVER2019;Database=EFCoreMigrationTest;Trusted_Connection=True;";
public DbSet<UserInfo> UserInfo { get; set; }
public DbSet<UserInfoExt> UserInfoExt { get; set; }
public DbSet<OrderInfo> OrderInfo { get; set; }
public DbSet<RoleInfo> RoleInfo { get; set; }
public DbSet<UserRoleMapping> UserRoleMapping { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(ConnectionString).UseLoggerFactory(MyLoggerFactory);
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//创建数据
modelBuilder.Entity<UserInfo>().HasData(new UserInfo()
{
Id = 1,
Name = "haha",
Age = 18
});
//一对一
modelBuilder.Entity<UserInfoExt>().HasOne(u => u.UserInfo).WithOne(u=>u.UserInfoExt).HasForeignKey<UserInfoExt>(e => e.UserInfoId);
//一对多
modelBuilder.Entity<UserInfo>().HasMany(u => u.OrderInfo).WithOne(o => o.UserInfo).HasForeignKey(o => o.UserInfoId);
//多对多
modelBuilder.Entity<UserRoleMapping>().HasOne(u => u.UserInfo).WithMany(u => u.UserRoleMapping).HasForeignKey(u => u.UserInfoId);
modelBuilder.Entity<UserRoleMapping>().HasOne(u => u.RoleInfo).WithMany(u => u.UserRoleMapping).HasForeignKey(u => u.RoleInfoId);
//也可以这样
modelBuilder.Entity<UserRoleMapping>().HasKey(p => new { p.UserInfoId, p.RoleInfoId });
}
}
添加数据
EFCoreMigrationContext context = new EFCoreMigrationContext();
UserInfo userInfo = new UserInfo() { Name = "aa", Age = 18 };
userInfo.UserInfoExt = new UserInfoExt() { Sign = "aaa" };
userInfo.OrderInfo = new List<OrderInfo>()
{
new OrderInfo(){ Content ="订单1"},
new OrderInfo(){ Content="订单2"}
};
context.UserInfo.Add(userInfo);
context.SaveChanges();
var user = context.UserInfo.FirstOrDefault();