【问题标题】:Using EF Core HasQueryFilter on navigation properties在导航属性上使用 EF Core HasQueryFilter
【发布时间】:2018-05-09 02:30:42
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:

    如前所述,这些模型级过滤器(尚未)用于导航属性。这很可悲,因为人们可能没有意识到这种限制并在多租户架构中依赖它。每个人都知道,在多租户应用程序中出错可能会导致您公司的死亡,因此正确执行此操作非常重要。

    一旦您选择了通过 TenantId 进行租户分离(而不是更安全的每租户架构或每租户数据库),并且知道 EF-core 中的当前限制,您可能想要构建一个确保至少在保存更改时不会混淆租户数据。

    这个保护可以通过定义一个接口来实现:

    public interface IHasTenantId
    {
        int TenantId { get; }   
    }
    

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

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

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

    【讨论】:

    【解决方案2】:

    你不能。这是当前(截至 EF Core 2.0.1)Global Query Filters 实现的记录限制:

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

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

    【讨论】:

    • 是的,太糟糕了,他们把它作为一个半生不熟的功能推出了。另一个混淆和 SO 问题的来源。
    • @GertArnold 是的 :( 我已经不得不处理second limitation 这对我来说也没有逻辑意义,因为“常规”查询过滤器没有这样的要求。
    • 此限制已在 EF Core 2.1 中删除。您现在可以在导航属性中使用 HasQueryFilters。 github.com/dotnet/efcore/issues/8881
    猜你喜欢
    • 1970-01-01
    • 2022-01-01
    • 2018-10-22
    • 2018-10-10
    • 2020-07-04
    • 1970-01-01
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    相关资源
    最近更新 更多