需要一种方法来获取当前请求 URL 以在多租户应用程序中配置数据库上下文
Need a way to get the current request URL to configure the database context in multi-tenant application
我正在将 Web 应用程序从 asp.net mvc 迁移到 .net core (.net 5),这让我陷入困境。
该站点在 IIS 中配置为接受来自多个 URL 的请求,例如 site1.example.com 和 site2.example.com。每个站点都有自己的数据库,通过 entity framework 核心访问。
在旧的 .net 框架中,我能够使用 global.asax.cs 中的事件之一来解析传入请求 URL 并从配置文件中查找正确的租户数据库。我正在尝试在 asp.net core mvc.
中设置类似的东西
这是 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...
}
然后租户标识符如下所示:
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
}
}
现在有我不知道的正确方法吗?当我直到运行时才知道连接字符串键时,如何为依赖注入设置 entity framework 数据库上下文?我会在 IIS 中配置单独的站点和虚拟目录吗?
重构 DbContext
以覆盖 OnConfiguring
成员。注入配置和上下文访问器并在那里执行配置。
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);
}
}
在 DbContext
正在 created/initialized 时尝试访问请求上下文在请求流中为时过早,无法访问所需信息。它需要在上下文已经初始化和注入之后发生。
public void ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
services.AddSingleton<ITenantIdentifier, UrlTenantIdentifier>();
services.AddDbContext<myDbContext>(); //Simplified since configuration is internal
//other services configured below...
}
我正在将 Web 应用程序从 asp.net mvc 迁移到 .net core (.net 5),这让我陷入困境。 该站点在 IIS 中配置为接受来自多个 URL 的请求,例如 site1.example.com 和 site2.example.com。每个站点都有自己的数据库,通过 entity framework 核心访问。
在旧的 .net 框架中,我能够使用 global.asax.cs 中的事件之一来解析传入请求 URL 并从配置文件中查找正确的租户数据库。我正在尝试在 asp.net core mvc.
中设置类似的东西这是 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...
}
然后租户标识符如下所示:
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
}
}
现在有我不知道的正确方法吗?当我直到运行时才知道连接字符串键时,如何为依赖注入设置 entity framework 数据库上下文?我会在 IIS 中配置单独的站点和虚拟目录吗?
重构 DbContext
以覆盖 OnConfiguring
成员。注入配置和上下文访问器并在那里执行配置。
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);
}
}
在 DbContext
正在 created/initialized 时尝试访问请求上下文在请求流中为时过早,无法访问所需信息。它需要在上下文已经初始化和注入之后发生。
public void ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
services.AddSingleton<ITenantIdentifier, UrlTenantIdentifier>();
services.AddDbContext<myDbContext>(); //Simplified since configuration is internal
//other services configured below...
}