简体   繁体   English

需要一种方法来获取当前请求 URL 以在多租户应用程序中配置数据库上下文

[英]Need a way to get the current request URL to configure the database context in multi-tenant application

I am migrating a web app from asp.net mvc to .net core (.net 5), and this has got me stuck.我正在将 web 应用程序从 asp.net mvc 迁移到 .net 核心(.net 5),这让我陷入困境。 The site is configured in IIS to accept request from multiple URLs like site1.example.com and site2.example.com.该站点在 IIS 中配置为接受来自多个 URL 的请求,例如 site1.example.com 和 site2.example.com。 Each site has its own database, accessed through entity framework core.每个站点都有自己的数据库,通过实体框架核心访问。

In the old .net framework, I was able to use one of the events in the global.asax.cs to parse the incoming request URL and lookup the correct tenant database from a configuration file.在旧的 .net 框架中,我能够使用 global.asax.cs 中的事件之一来解析传入的请求 URL 并从配置文件中查找正确的租户数据库。 I'm trying to set up something similar in asp.net core mvc.我正在尝试在 asp.net 核心 mvc 中设置类似的东西。

Here's the relevant part of my ConfigureServices method in the startup.cs这是我在 startup.cs 中的 ConfigureServices 方法的相关部分

public void ConfigureServices(IServiceCollection services)
{           
    services.AddHttpContextAccessor();
    services.AddSingleton<ITenantIdentifier, UrlTenantIdentifier>();
    services.AddDbContext<myDbContext>((serviceProvider, dbContextBuilder) =>
    {
        var tenantIdentifier = serviceProvider.GetRequiredService<ITenantIdentifier>();
        var connectionString = Configuration.GetConnectionString(tenantIdentifier.GetCurrentTenantId() + "myDataModel");
        dbContextBuilder.UseSqlServer(connectionString);
    }, ServiceLifetime.Scoped);

    //other services configured below...
}

Then the tenant identifier looks like this:然后租户标识符如下所示:

public interface ITenantIdentifier
{
    string GetCurrentTenantId();
}

public class UrlTenantIdentifier : ITenantIdentifier
{
    readonly IHttpContextAccessor _httpContextAccessor;
    readonly ILogger<UrlTenantIdentifier> _logger;

    public UrlTenantIdentifier(IHttpContextAccessor httpContextAccessor, ILogger<UrlTenantIdentifier> logger)
    {
        _httpContextAccessor = httpContextAccessor;
        _logger = logger;
    }

    public string GetCurrentTenantId()
    {
        //_httpContextAccessor is null here

        //logic below for parsing URL and finding if we're site1 or site2
    }
}

Is there a correct way of doing this now that I'm not aware of?现在我不知道有正确的方法吗? How can I set up the entity framework database context for dependency injection when I don't know the connection string key until runtime?当我直到运行时才知道连接字符串键时,如何为依赖注入设置实体框架数据库上下文? Am I going to be stuck configuring separate sites and virtual directories in IIS?我会不会在 IIS 中配置单独的站点和虚拟目录?

Refactor the DbContext to override the OnConfiguring member.重构DbContext以覆盖OnConfiguring成员。 Inject configuration and context accessor and perform configuration there.注入配置和上下文访问器并在那里执行配置。

public class myDbContext : DbContext {
    private readonly ITenantIdentifier tenantIdentifier;
    private readonly IConfiguration configuration;

    public myDbContext(IConfiguration configuration, ITenantIdentifier tenantIdentifier) {
        this.configuration = configuration;
        this.tenantIdentifier = tenantIdentifier;
    }
    
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) {
        var connectionString = configuration
            .GetConnectionString(tenantIdentifier.GetCurrentTenantId() + "myDataModel");
        optionsBuilder.UseSqlServer(connectionString);
    }
}

Trying to access the request context at the time the DbContext is being created/initialized is too early in the request flow to get access to the desired information.在创建/初始化DbContext时尝试访问请求上下文在请求流中为时过早,无法访问所需的信息。 It needs to happen after the context has already been initialized and injected.它需要在上下文已经初始化和注入之后发生。

public void ConfigureServices(IServiceCollection services)  
    services.AddHttpContextAccessor();
    services.AddSingleton<ITenantIdentifier, UrlTenantIdentifier>();
    services.AddDbContext<myDbContext>(); //Simplified since configuration is internal

    //other services configured below...
}

Reference DbContext Lifetime, Configuration, and Initialization参考DbContext 生命周期、配置和初始化

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 连接到多租户应用程序的数据库? - Connecting to database for Multi-Tenant application? 多租户应用程序中的IdentityRole - IdentityRole in multi-tenant application 多租户解析管理站点中的租户上下文 - Multi-tenant resolve tenant context in admin site 如何在多租户数据库中处理ClientId - How to handle ClientId in multi-tenant database 多租户ASP .NET应用程序中的隔离 - Isolation in a Multi-tenant ASP .NET Application 对于多租户数据库,将租户 ID 作为 GET 参数传递给 API 是否安全? - For a Multi-Tenant database, is it safe to pass Tenant ID's as GET parameters to the API? 在多租户环境中,使用 .Net Core,如何配置 Windows 服务以针对正确的数据库 - In a multi-tenant environment, using .Net Core, how to configure a Windows Service to target the correct database 通过上下文覆盖将基于 EF 的应用程序转换为多租户 - Convert EF-based app to multi-tenant by way of context overrides Azure 数据库水平分片是多租户 C# asp.net 应用程序的最佳解决方案 - Azure Database Horizontal Sharding the best solution for Multi-tenant C# asp.net application 单租户到多租户 - Single tenant to multi-tenant
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM