问题描述
我正在尝试对多租户查询应用过滤器,但是当该属性是导航属性的一部分时,它不允许我应用该过滤器:
I'm trying to apply a filter to my queries for multi-tenancy but it doesn't allow me to apply the filter when the property is part of a navigation property:
modelBuilder.Entity<Level>().HasQueryFilter(lvl => lvl.SchoolYear.TenantId == _tenantProvider.TenantId);
这里,Level是我要过滤的属性,但TenantId用于过滤的属性位于Level.SchoolYear中.
Here, Level is the property I want filtered but the property to use for filtering which is TenantId is is inside Level.SchoolYear.
如果它是顶级属性,则可以正常工作.当我需要过滤的属性是导航属性时,如何应用全局过滤器?
If its a top-level property it works fine. How can I apply a global filter when the property I need for filtering is a navigation property?
推荐答案
如上所述,尚未为导航属性实现这些模型级别的过滤器.令人遗憾的是,因为人们可能没有意识到这一限制,而在多租户体系结构中依靠它.每个人都知道,在多租户应用程序中犯错可能是您公司的灭亡,因此正确执行此操作至关重要.
As said, these model level filters are not (yet) implemented for navigation properties. Which is sad, because people may not be aware of this restriction and count on it in a multi-tenant architecture. Everybody knows that making errors in a multi-tenant application may be the death of your company, so it's pretty vital to do this right.
一旦您选择了通过 TenantId
进行租户分隔(而不是更安全的每租户架构或每租户数据库),并且知道EF核心中的当前限制,您可能希望建立一种保护措施,至少在保存更改时永远不会混淆租户数据.
Once you've chosen for tenant separation by TenantId
(and not the safer schema-per-tenant or database-per-tenant), and knowing this current restriction in EF-core, you may want to build in a safeguard that at least you'll never mix up tenant data when saving changes.
可以通过定义接口来实现此保护措施:
This safeguard could be implemented by defining an interface:
public interface IHasTenantId
{
int TenantId { get; }
}
...由具有 TenantId
的每个实体实施.
... to be implemented by each entity having a TenantId
.
然后在 DbContext
子类中的 SaveChanges
的替代中,可以检查更改集中的所有 TenantId
是否相同:
Then in an override of SaveChanges
in the DbContext
subclass there can be a check if all TenantId
s in a change set are identical:
public override int SaveChanges()
{
var distinctTenantIdsCount = this.ChangeTracker.Entries<IHasTenantId>()
.Select(e => e.Entity.TenantId)
.Distinct().Count();
if(distinctTenantIdsCount > 1)
{
// Throw an exception and handle it.
}
return base.SaveChanges();
}
这篇关于在导航属性上使用EF Core HasQueryFilter的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!