You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

整洁架构下分离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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 08:44:53