【发布时间】:2020-06-30 13:51:18
【问题描述】:
我有一个多租户 PostgreSQL 数据库,它使用行级安全性来控制租户应该能够看到的内容。
我正在使用 EF Core 和 ASP.NET Core 来访问这个数据库。为了处理租户访问,我使用连接拦截器来运行适当的数据库命令。例如:
为此,我创建了一个连接拦截器。
public override async Task ConnectionOpenedAsync(
DbConnection connection,
ConnectionEndEventData eventData,
CancellationToken cancellationToken = default)
{
using var command = connection.CreateCommand();
var commandText = string.Join("\r\n",
"SET SESSION ROLE TO tenant;",
$"SET SESSION tenant.userId TO '{this.userId}';");
command.CommandText = commandText;
await command.ExecuteNonQueryAsync(cancellationToken);
await base.ConnectionOpenedAsync(connection, eventData, cancellationToken);
}
所有这些都可以正常工作,但我还需要在非租户上下文中访问数据库。换句话说,我不希望上面的拦截器一直运行。
我正在努力寻找最好的方法来做到这一点。我最初的尝试是使用接口来定义租户或“全局”接口
// (MyDbContext implements both IMyTenantDbContext and IMyGlobalDbContext)
services.AddDbContext<IMyTenantDbContext, MyDbContext>((sp, options) =>
{
var tenantInterceptor = sp.GetRequiredService<SetTenantConnectionInterceptor>();
options
.UseNpgsql(connectionString)
.AddInterceptors(tenantInterceptor);
});
services.AddDbContext<IMyGlobalDbContext, MyDbContext>(options =>
{
options
.UseNpgsql(connectionString);
});
但由于某种原因,DI 系统使用第一个 AddDbContext,即使我尝试注入 IMyGlobalDbContext 意味着仍在使用拦截器。
我确信一定有更好的方法来做到这一点,所以如果我做的完全错误,请告诉我。
【问题讨论】:
标签: c# entity-framework-core ef-core-3.1