在导航属性上使用EF Core HasQueryFilter

g_b*_*g_b 4 c# entity-framework-core asp.net-core

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

modelBuilder.Entity<Level>().HasQueryFilter(lvl => lvl.SchoolYear.TenantId == _tenantProvider.TenantId);
Run Code Online (Sandbox Code Playgroud)

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

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

Ger*_*old 6

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

一旦通过选择租户分离TenantId(而不是更安全的架构,每个租户或数据库,每个租户),并知道在EF-核心这个电流限制,你可能想建立一个保障,至少你"保存更改时,永远不会混淆租户数据.

可以通过定义接口来实现此安全措施:

public interface IHasTenantId
{
    int TenantId { get; }   
}
Run Code Online (Sandbox Code Playgroud)

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

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

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();
}
Run Code Online (Sandbox Code Playgroud)


Iva*_*oev 5

你不能。这是当前(从 EF Core 2.0.1 开始)全局查询过滤器实现的记录限制:

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

它由#8881跟踪:允许在模型级实体过滤器增强请求中使用导航,但不幸的是没有分配具体的里程碑,这意味着我们不知道它是否以及何时修复。

  • 是的,太糟糕了,他们把它作为一个半生不熟的功能推出了。另一个混乱和 SO 问题的来源。 (2认同)