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

.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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:43:10