c# - 需要一种获取当前请求 URL 以在多租户应用程序中配置数据库上下文的方法
问题描述
我正在将 Web 应用程序从 asp.net mvc 迁移到 .net core (.net 5),这让我陷入了困境。该站点在 IIS 中配置为接受来自多个 URL 的请求,例如 site1.example.com 和 site2.example.com。每个站点都有自己的数据库,通过实体框架核心访问。
在旧的 .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
}
}
现在我不知道有正确的方法吗?当我直到运行时才知道连接字符串键时,如何为依赖注入设置实体框架数据库上下文?我会被困在 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
为时过早,无法访问所需的信息。它需要在上下文已经初始化和注入之后发生。
public void ConfigureServices(IServiceCollection services)
services.AddHttpContextAccessor();
services.AddSingleton<ITenantIdentifier, UrlTenantIdentifier>();
services.AddDbContext<myDbContext>(); //Simplified since configuration is internal
//other services configured below...
}
推荐阅读
- python - Line2D服装图例只有一点
- uiscrollview - 使用带有 iOS 13 可拉动模式的无限滚动 UICollectionView
- node.js - 为什么使用 n 安装 nodejs ubuntu 时缺少目录?
- mysql - Mysql:比较一张表中两列的值
- php - Laravel Imap connect() 慢 | 重用?
- jquery - 使用 jquery 在开始时重置时间计数器
- javascript - Nuxt.js:全局 mixin 仅在服务器端工作
- reporting-services - 列超链接并将数据从主报告传递到其他报告
- arduino - 在与 HC-05 的 Arduino 连接中,串行通信无法正常工作
- java - 从 webapplicationexception 返回 JSON 正文中的错误