整洁架构下分离DbContext层:EF Core迁移生成空文件求助
我正在实现整洁架构,遵循宿主层不引用数据层的原则,参考ABP框架的方式,使用HostDbContext(即DesignTimeDbContext)仅用于EF Core迁移操作,数据层的MainApplicationDbContext负责数据库连接。
数据层的MainApplicationDbContext代码:
namespace EntityCore.Data { public class MainApplicationDbContext : DbContext { public MainApplicationDbContext(DbContextOptions<MainApplicationDbContext> options) : base(options) { } public DbSet<Movie> Movies { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Movie>(b => { b.ToTable("MoviesDBO"); b.HasIndex(t => t.Id); b.Property(t => t.Name).IsRequired(); }); } } }
宿主层的ApplicationDbContext(即HostDbContext)代码:
namespace MoviesHost.efCore { public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } } }
DesignTimeDbContext工厂配置:
namespace MoviesHost.efCore { public class ApplicationContextFactory : IDesignTimeDbContextFactory<ApplicationDbContext> { public ApplicationDbContext CreateDbContext(string[] args) { var configuration = BuildConfiguration(); var builder = new DbContextOptionsBuilder<ApplicationDbContext>() .UseSqlServer(configuration.GetConnectionString("DefaultConnection")); return new ApplicationDbContext(builder.Options); } private static IConfigurationRoot BuildConfiguration() { var builder = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("appsettings.json"); return builder.Build(); } } }
执行迁移命令添加迁移后,生成的迁移文件是空的:
namespace MoviesHost.Migrations { /// <inheritdoc /> public partial class initDatabase : Migration { /// <inheritdoc /> protected override void Up(MigrationBuilder migrationBuilder) { } /// <inheritdoc /> protected override void Down(MigrationBuilder migrationBuilder) { } } }
请问该如何解决迁移文件为空的问题?
迁移文件为空的核心原因是:宿主层的ApplicationDbContext没有包含任何实体的模型配置,EF Core无法检测到需要生成的数据库结构。要在遵守宿主层不引用数据层的前提下解决这个问题,需要把实体配置抽离到独立的共享类库,让数据层和宿主层都能复用这些配置。
步骤1:抽离实体配置到独立类库
创建一个独立的类库项目(比如命名为EntityCore.Configurations),将实体的配置逻辑从MainApplicationDbContext中迁移到实现IEntityTypeConfiguration<T>的类中:
namespace EntityCore.Configurations { public class MovieConfiguration : IEntityTypeConfiguration<Movie> { public void Configure(EntityTypeBuilder<Movie> builder) { builder.ToTable("MoviesDBO"); builder.HasIndex(t => t.Id); builder.Property(t => t.Name).IsRequired(); } } }
步骤2:修改数据层的MainApplicationDbContext
在OnModelCreating方法中,通过程序集加载所有实体配置,替代原来硬编码的配置逻辑:
namespace EntityCore.Data { public class MainApplicationDbContext : DbContext { public MainApplicationDbContext(DbContextOptions<MainApplicationDbContext> options) : base(options) { } public DbSet<Movie> Movies { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 加载共享类库中的所有实体配置 modelBuilder.ApplyConfigurationsFromAssembly(typeof(MovieConfiguration).Assembly); } } }
步骤3:修改宿主层的ApplicationDbContext
让宿主层的ApplicationDbContext同样加载共享类库中的实体配置,并添加对应的DbSet(确保EF Core能检测到实体):
namespace MoviesHost.efCore { public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } // 添加实体DbSet,让EF Core识别实体 public DbSet<Movie> Movies { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); // 加载共享类库中的所有实体配置 modelBuilder.ApplyConfigurationsFromAssembly(typeof(MovieConfiguration).Assembly); } } }
步骤4:重新生成迁移
执行迁移命令时,指定宿主项目和对应的ApplicationDbContext:
- 使用Package Manager Console:
Add-Migration initDatabase -Project MoviesHost -Context ApplicationDbContext - 使用.NET CLI:
dotnet ef migrations add initDatabase --project MoviesHost --context ApplicationDbContext
这样生成的迁移文件就会包含Movie实体对应的数据库表结构了。
内容的提问来源于stack exchange,提问作者ali Payande

