Ef Core 全局查询过滤器动态启用禁用

Ef Core Global Query Filter Enable Disable Dynamically

我正在尝试实现一个启用禁用条件的 ef 核心全局查询过滤器。根据我的情况,我有一个名为“FilterStatus”的标志,它的值会随着每个用户而变化。因此任何登录到系统的用户 FilterStatus 值都会更改。我想实现一个全局查询过滤器来根据 FilterStatus 标志过滤数据。

我想出了以下但不起作用的全局查询过滤器的 if-else 语句:

public partial class TableDbContext : DbContext, IDbContext
{
   protected Guid TenantId { get; set; }
   protected UserClaimFilter UserClaimFilter { get; set; } = new UserClaimFilter();

   protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
   {
        var tenant = _httpContextAccessor?.HttpContext?.GetTenant();
        if (tenant != null)
        {
            TenantId = Guid.Parse(tenant.Id);

            var userClaims =
                _httpContextAccessor.HttpContext.Session.GetObject<UserClaimFilter> 
                   (DefaultConstants
                    .SessionUserClaimStore);

            if (userClaims != null)
            {
                UserClaimFilter = userClaims;
            }
        }
   }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
            modelBuilder.Entity<Region>(entity =>
            {

                if (UserClaimFilter.FilterStatus && UserClaimFilter.RegionClaims.Any())
                {
                    entity.HasQueryFilter(a => a.TenantId == TenantId && 
                      UserClaimFilter.RegionClaims.Contains(a.RegionCode));
                }
                else
                {
                    entity.HasQueryFilter(a => a.TenantId == TenantId);
                }

            });
   }
}

在上面的代码中总是 运行 else 部分,即使 UserClaimFilter.FilterStatus 为真。我想是因为第一次 运行 的 OnModelCreating 默认值 UserClaimFilter.FilterStatus 是假的。

有没有根据配置值启用-禁用全局查询过滤器的解决方案?

全局查询过滤条件的所有动态部分必须 (1) 来自 DbContext 成员(与您的代码一样)并且 (2) 是表达式的一部分,而不是在构建表达式时计算一次. EF Core 具有在翻译查询时消除条件表达式的常量 true 或 false 部分的机制,因此您只需将它们包含在表达式中即可。例如

entity.HasQueryFilter(a => a.TenantId == TenantId &&
    (!UserClaimFilter.FilterStatus ||
     !UserClaimFilter.RegionClaims.Any() || 
     UserClaimFilter.RegionClaims.Contains(a.RegionCode))
);

将过滤器应用于查询时,如果 !UserClaimFilter.FilterStatus!UserClaimFilter.RegionClaims.Any() 为真 当时 ,则整个表达式 (a || b || c)将被视为 constant true 并从生成的查询中删除(因为 (x && true) == x)。

更新: 如评论中所述,目前 EF Core 并未完全消除整个表达式。 a || b 替换为具有 truefalse 值的 bool 参数。但是当 bool 参数值为 true.

时,至少 c (这是实际的过滤器,在您的情况下为 UserClaimFilter.RegionClaims.Contains(a.RegionCode) )被消除