.NET 5多租户项目升级至.NET 7时MemoryDbContext注入报错问题
升级.NET 5多租户项目至.NET 7时MemoryDbContext未注册的问题解决
问题场景
将基于.NET 5的子域名识别多租户项目升级到.NET 7后,执行数据库初始化代码时抛出异常,提示Site.DataLayer.Context.MemoryDbContext服务未注册。项目原本通过子域名(如city-a.site.com)识别租户,用MemoryDbContext存储租户数据,TenantAttribute作为ActionFilter实现租户校验,在.NET 5中运行正常。
错误信息
System.InvalidOperationException HResult=0x80131509 Message=No service for type 'Site.DataLayer.Context.MemoryDbContext' has been registered. Source=Microsoft.Extensions.DependencyInjection.Abstractions StackTrace: at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType) at Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService[T](IServiceProvider provider) at Program.
错误原因分析
问题出在.NET 7的初始化代码逻辑上:
- 服务容器不共享:你通过
WebApplication.CreateBuilder(args)构建的应用容器已经在ConfigureServices中注册了MemoryDbContext,但后续又用Host.CreateDefaultBuilder(args).Build()创建了一个全新的独立宿主容器,这个新容器并没有继承之前配置的任何服务,包括MemoryDbContext。 - 初始化顺序错误:在.NET 7的最小API模型中,必须先完成Web应用的构建,再使用应用自身的服务容器执行初始化逻辑,而非单独创建无关的宿主实例。
修复方案
修改.NET 7的初始化代码,直接使用WebApplication的服务容器执行数据库初始化:
var builder = WebApplication.CreateBuilder(args); ConfigureLogging(builder.Logging, builder.Environment, builder.Configuration); ConfigureServices(builder.Services, builder.Configuration, builder.Environment); // 先完成Web应用构建 var webApp = builder.Build(); // 使用Web应用的服务容器创建作用域 using (var scope = webApp.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService<MemoryDbContext>(); context.Database.EnsureCreated(); if (!context.Tenants.Any()) { context.Tenants.Add(new Tenant() { Name = "City1", Host = "city-a", Cog = 2, MainId = 1, SubId = "1" }); context.Tenants.Add(new Tenant() { Name = "City2", Host = "city-b", Cog = 2, MainId = 2, SubId = "2" }); context.SaveChanges(); } } // 启动Web应用 webApp.Run();
额外优化提示
- 你的
TenantAttribute通过构造注入MemoryDbContext,当前services.AddScoped(typeof(TenantAttribute))的注册方式可正常工作,但更规范的做法是在控制器/Action上使用[ServiceFilter(typeof(TenantAttribute))],配合现有服务注册,能更好地利用DI容器的生命周期管理。 - 原
TenantAttribute中fullAddress可能为空,直接访问fullAddress.Length会触发空引用异常,建议补充空值校验:var fullAddress = actionExecutingContext.HttpContext?.Request? .Headers?["Host"].ToString()?.Split('.'); if (fullAddress == null || fullAddress.Length < 2) { // 重定向逻辑 }
内容的提问来源于stack exchange,提问作者ioxoi
相关产品推荐
相关产品推荐

