首先在单个项目中使用EFCore是很简单的,看看微软官网的文档几乎不会出现迁移的问题
但是我的习惯是把与表相关的实体类和创建的迁移文件全部单独放在一个程序集中,这样便于集中管理,而且还可以把数据层共享给多个应用层,减少重复写代码
我的应用层的程序集是WpfApp,是一个WPF程序,数据层的程序集是WpfApp.Reponsitory,是一个类库。如下图
我的环境:
.NET6
EFCore 7.0.5
WpfApp.Reponsitor 项目
1,首先安装Nuget包,我用的是sqlite,所以安装Microsoft.EntityFrameworkCore.Sqlite,如果用MySQL就安装Pomelo.EntityFrameworkCore.MySql
2,编写实体类
public class Student { public int Id { get; set; } public string Name { get; set; } public int Age { get; set; } }
3,编写实体类配置类,我这里仅仅配置了表的名称
public class StudentEntityConfig : IEntityTypeConfiguration<Student> { public void Configure(EntityTypeBuilder<Student> builder) { builder.ToTable("t_student"); } }
4,编写数据库上下文类,下面的两个重写方法可以不重写,自定义的有参构造函数用来接收应用层的配置
public class MyDbContext : DbContext { public DbSet<Student> Students { get; set; } public MyDbContext(DbContextOptions options) : base(options) { } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { base.OnConfiguring(optionsBuilder); } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly); } }
WpfApp项目
1,项目引用 WpfApp.Reponsitor
2,安装Nuget包,Microsoft.EntityFrameworkCore.Design
3,编写上下文创建工厂类,因为EF执行手动迁移的时候(执行命令:Update-Database),要先通过默认的DbContextFactory构造一个数据库上下文对象,也就是MyDbContext对象,然而上面代码中可以看出,我们没有在MyDbContext中配置数据库的连接字符串等配置,
所以迁移是执行不成功的,因为它都不知道要将表创建在哪里,因此我们自己定义一个MyDbContextFactory,重写CreateDbContext返回我们自己创建的上下文对象。否则的话即使我们可以成功构建迁移文件,但是不能直接迁移到数据库中(手动迁移)
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext> { public MyDbContext CreateDbContext(string[] args) { string connectionString = ConfigurationManager.AppSettings["sqliteConnDev"]; var builder = new DbContextOptionsBuilder<MyDbContext>() .UseSqlite(connectionString); return new MyDbContext(builder.Options); } }
使用代码自动迁移:
很多时候我们希望应用程序启动后,自动检查数据库是否存在,不存在的话自动创建,表是否存在,不存在的话也自动创建。下面就来演示一下代码自动迁移
1,定义一个迁移方法
public static async Task Migration(string connectionString) { var builder = new DbContextOptionsBuilder<MyDbContext>() .UseSqlite(connectionString); using MyDbContext dbContext = new MyDbContext(builder.Options); //执行迁移 //如果数据库存在并且包含任何表,则不执行任何操作。 不执行任何操作来确保数据库架构与实体框架模型兼容。 //如果数据库存在但没有任何表,则使用实体框架模型创建数据库架构。 //如果数据库不存在,则创建数据库并使用实体框架模型创建数据库架构。 await dbContext.Database.EnsureCreatedAsync(); }
2,项目启动的时候调用上面的迁移方法,有了这一步你甚至不需要先构建迁移文件就可以直接执行迁移
public partial class App : Application { private string connectionString = ConfigurationManager.AppSettings["sqliteConnPro"]; protected override async void OnStartup(StartupEventArgs e) { base.OnStartup(e); await AutoMigrationHelper.Migration(connectionString); } }
以上代码已经上传GitHub仓库:jinleil/EFCoreTest: EFCore迁移在分层项目中的应用测试 (github.com)