.NET Core 6 API执行EF Core启动迁移后接口返回404问题
问题根因
数据库初始化逻辑放置位置错误,干扰了ASP.NET Core MVC的控制器路由发现流程:
- EF Core执行
MigrateAsync()时,会先完成DbContext模型构建,扫描当前程序集中所有定义的迁移类,这个过程会触发程序集类型全量加载 - 你把这段扫描逻辑放在了
app.MapControllers()(MVC端点注册、控制器路由发现的核心逻辑)之前,且包裹在开发环境的条件分支内:迁移执行时的类型预加载,会导致后续MVC框架执行控制器发现时,跳过本应注册的控制器路由,最终所有接口返回404 - 第二次启动时无待执行迁移,
MigrateAsync()不会触发,不会提前干扰控制器发现流程,因此路由可正常访问
修复方法
将数据库初始化逻辑从开发环境判断分支中移出,放到所有中间件注册、端点映射配置完成后,app.Run()启动应用之前,禁止在中间件管道配置流程中插入数据库初始化操作。
修改后的Program.cs核心代码结构如下:
// 先完成所有中间件注册,过程中不要插入数据库初始化逻辑 if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } else { app.UseHsts(); app.Use((context, next) => { context.Request.Host = new HostString(app.Configuration["AppDomain"]); context.Request.Scheme = "https"; return next(); }); } app.UseSerilogRequestLogging(); app.UseHttpsRedirection(); app.UseExceptionHandling(); app.UseAuthentication(); app.UseAuthorization(); // 先完成控制器端点映射 app.MapControllers(); // 所有管道配置完成后,再执行数据库初始化 using (var scope = app.Services.CreateScope()) { var databaseInitializer = scope.ServiceProvider.GetRequiredService<DatabaseInitializer>(); await databaseInitializer.InitializeDatabase(); } // 最后启动应用 app.Run();
优化建议
- 无需在
MigrateAsync()前额外调用GetPendingMigrations().Any()做判断,MigrateAsync()内部自带待执行迁移检查逻辑,不会重复执行已应用的迁移,额外判断反而会多一次数据库查询开销 - 多实例部署的生产环境不建议使用启动自动迁移方案,容易出现多实例并发执行迁移的冲突问题,建议将迁移作为独立发布流程执行
内容的提问来源于stack exchange,提问作者Popay
相关产品推荐
相关产品推荐

