【发布时间】:2020-04-20 01:20:50
【问题描述】:
我有一个多租户应用程序,用户在成功登录后会被重定向到一个页面,他可以在该页面上选择他想要合作的企业。
我需要添加很多依赖于企业 ID 的全局过滤器。但似乎 OnModelCreating 在创建 dbcontext 时被调用。 dbcontext 是在用户想要登录时创建的,但是,此时我还不知道他想要使用的企业,因为他还没有选择它。所以,我不能添加过滤器。
我想在选择企业 ID 时添加这些过滤器。可能吗?因为我看到的所有示例都将它们添加到 OnModelCreating 中,并且在其他地方没有找到任何参考。
这是 OnModelCreating 方法的一个示例:
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
//Last in wins so first set base model features
base.OnModelCreating(modelBuilder);
HttpContext httpContext = _httpContextAccessor.HttpContext;
if (httpContext.Request.Headers.ContainsKey("X-TENANT-ID") == true)
{
string tenant = httpContext.Request.Headers["X-TENANT-ID"];
int enterpriseId = int.Parse(tenant);
//Define global filters for all entities
modelBuilder.Entity<Enterprise>().HasQueryFilter(p => !p.IsDeleted);
modelBuilder.Entity<Vehicle>().HasQueryFilter(o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
modelBuilder.Entity<BillingInfo>().HasQueryFilter( o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
modelBuilder.Entity<DriverAppUser>().HasQueryFilter( o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
modelBuilder.Entity<Agency>().HasQueryFilter( o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
modelBuilder.Entity<InsuranceCarrier>().HasQueryFilter( o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
modelBuilder.Entity<Particular>().HasQueryFilter( o => o.EnterpriseId == enterpriseId && !o.IsDeleted);
}
}
你会怎么做?
【问题讨论】:
-
我们最近在我们的应用程序中使用了几乎相同的问题和场景,用户可以选择他的租户。如果您的 Context 在用户加载第二页(需要过滤器的页面)时设置为瞬态或作用域,则应创建一个新的上下文,该上下文将再次通过此 OnModelCreating 运行。此外,由于您的 X-TENANT-ID 在 Http 标头中,请确保您已验证用户没有恶意发送他们实际上无权访问的租户 ID。
-
@JeffreyParks 我使用扩展方法 services.AddDbContext 添加了 DbContext,并且可以向您保证 OnModelCreating 只是在第一次向 WebApi 发出请求时被调用。我一直在检查来源,并且此扩展方法将服务注册为范围。那么,它对您有何帮助? :/。瞬态不是一种选择。
-
我想我需要多睡一会儿。您声明要创建一个新的 dbContext。您是否介意添加一些代码来查看如何创建这个新的 dbcontext 以及如何添加到依赖项注入系统中?我真的很感激。
-
当请求到达服务器时,它会创建 Controller/Service/DbContext 的新实例(不知道你有什么层次结构,但它是相同的概念)。这意味着每个 HTTP 请求都会获得一个新的 DbContext,这意味着如果所有内容都设置为 Transient 和/或 Scoped,您的代码应该可以正常工作。如果以后有更多时间,我可以发布一个完整的示例作为答案。
-
只是补充一点信息。实体框架有一个缓存系统。该文档明确指出,克服它可能会导致性能问题。我开始考虑不使用全局过滤器,并使用一些辅助方法来添加常见的过滤器,如租户和软删除。无论如何,我将非常感谢您如何建立您的解决方案。谢谢!
标签: asp.net-core .net-core entity-framework-core