使用.NET 6+CQRS+MediatR搭建分层API时EF Core迁移报错求助
解决.NET 6分层API中EF Core无法创建DbContext实例的迁移问题
问题重现
执行首次EF Core迁移时触发异常:Unable to create an object of type 'WorldCupApiDbContext'
场景:使用.NET 6结合CQRS与MediatR搭建分层Web API,已尝试指定MigrationsAssembly配置,但问题未解决。
相关代码
Program.cs
using System.Reflection; using MediatR; using Microsoft.EntityFrameworkCore; using WorldCupApi.Application.Handler.QueryHandler; using WorldCupApi.Repository.Entities; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddDbContextPool<WorldCupApiDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")); }); builder.Services.AddMediatR(typeof(GetGroupQueryHandler).GetTypeInfo().Assembly); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseHttpsRedirection(); app.UseAuthorization(); app.MapControllers(); app.Run();
WorldCupApiDbContext.cs
using Microsoft.EntityFrameworkCore; namespace WorldCupApi.Repository.Entities; public class WorldCupApiDbContext : DbContext { public WorldCupApiDbContext(DbContextOptions<WorldCupApiDbContext> options) : base(options) { } //entities public DbSet<Group> Groups { get; set; } public DbSet<Team> Teams { get; set; } }
已尝试的配置修改
builder.Services.AddDbContextPool<WorldCupApiDbContext>(options => { options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"), b=> b.MigrationsAssembly("WorldCupApi.Repository")); });
解决方案
1. 显式指定迁移命令的项目参数
分层架构下,EF Core工具无法自动识别启动项目和DbContext所在项目,需要在命令行中明确指定:
# 替换为你的实际项目名称 dotnet ef migrations add InitialCreate --project WorldCupApi.Repository --startup-project WorldCupApi.Web
2. 实现IDesignTimeDbContextFactory(官方推荐方案)
在WorldCupApi.Repository项目中添加工厂类,让迁移工具能正确初始化DbContext:
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore.Design; using Microsoft.Extensions.Configuration; using System.IO; namespace WorldCupApi.Repository.Entities; public class WorldCupApiDbContextFactory : IDesignTimeDbContextFactory<WorldCupApiDbContext> { public WorldCupApiDbContext CreateDbContext(string[] args) { // 加载Web项目的配置文件,确保连接字符串一致 IConfigurationRoot configuration = new ConfigurationBuilder() .SetBasePath(Directory.GetCurrentDirectory()) .AddJsonFile("../WorldCupApi.Web/appsettings.json") // 根据实际项目路径调整 .Build(); var optionsBuilder = new DbContextOptionsBuilder<WorldCupApiDbContext>(); optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly("WorldCupApi.Repository")); return new WorldCupApiDbContext(optionsBuilder.Options); } }
3. 验证连接字符串配置
确保Web项目的appsettings.json中存在有效连接字符串:
{ "ConnectionStrings": { "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=WorldCupApiDb;Trusted_Connection=True;MultipleActiveResultSets=true" } }
4. 临时方案:添加无参构造函数(不推荐生产环境使用)
迁移工具在部分场景下会尝试使用无参构造函数创建实例,可临时添加:
public class WorldCupApiDbContext : DbContext { // 保留原有依赖注入构造函数 public WorldCupApiDbContext(DbContextOptions<WorldCupApiDbContext> options) : base(options) { } // 仅用于迁移的无参构造函数 protected WorldCupApiDbContext() { } // ... DbSet定义 }
内容的提问来源于stack exchange,提问作者burakkorman
相关产品推荐
相关产品推荐

