在导航属性上使用EF Core HasQueryFilter

时间:2017-11-25 08:36:12

标签: c# asp.net-core entity-framework-core

我正在尝试将过滤器应用于我的多租户查询,但是当属性是导航属性的一部分时,它不允许我应用过滤器:

modelBuilder.Entity<Level>().HasQueryFilter(lvl => lvl.SchoolYear.TenantId == _tenantProvider.TenantId);

这里,Level是我想要过滤的属性,但TenantId用于过滤的属性在Level.SchoolYear中。

如果它是顶级属性,它可以正常工作。当我需要过滤的属性是导航属性时,如何应用全局过滤器?

2 个答案:

答案 0 :(得分:6)

如上所述,这些模型级别过滤器尚未(导航)属性实现。这很难过,因为人们可能没有意识到这种限制并且在多租户架构中依赖它。每个人都知道在多租户应用程序中出错可能是你公司的死亡,所以做到这一点非常重要。

一旦您通过TenantId选择租户分离(而不是每个租户更安全的架构或每个租户的数据库),并且知道EF核心中的当前限制,您可能需要建立一个保障措施,至少在保存更改时,您永远不会混淆租户数据。

可以通过定义界面来实现此安全措施:

public interface IHasTenantId
{
    int TenantId { get; }   
}

...由具有TenantId的每个实体实施。

然后在SaveChanges子类中覆盖DbContext,可以检查更改集中的所有TenantId是否相同:

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();
}

答案 1 :(得分:4)

你不能。它是当前(从EF Core 2.0.1开始)Global Query Filters实施的文档限制:

  

过滤器不能包含对导航属性的引用。

#8881: Allow to use navigations in model level entity filters增强请求跟踪,但遗憾的是没有分配具体里程碑,这意味着我们不知道是否以及何时修复。