You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EF Core全局查询过滤器失效:无法忽略IsDeleted筛选显示已删除文档

EF Core全局查询过滤器忽略失效排查与修复

问题背景

我通过仓储层的GetAllAsync方法查询KYC文档,代码实现如下:

var kycDocs = await _kycDocRepo.GetAllAsync(a => a.CreatedBy == query.UserId &&
            (query.Profile.Role == UserRoleName.Customer ? (a.Status == KYCDocumentStatus.Approved) :
            a.Status != KYCDocumentStatus.UploadInProgress),
            ignoreFilters: query.Profile.Role != UserRoleName.Customer,
            select: a => new CustomerIdentityItemDTO
            {
                Id = a.Id,
                Type = a.Type,
                IdentityNumber = a.IdentityNumber,
                IssuedOn = a.IssuedOn,
                CreatedOn = a.CreatedOn,
                ExpireOn = a.ExpireOn,
                DocumentUrl = a.DocumentUrl,
                Status = a.Status,
                SubType = a.SubType,
                ExpiryStatus = CustomerHelpers.GetDocumentValidityStatus(a.Type, a.ExpireOn)
            });

生成的原始SQL查询如下(可见仍带有全局过滤器的NOT (k.IsDeleted)条件):

SET @__query_UserId_0 = 1214;

SELECT `k`.`Id`, `k`.`Type`, `k`.`IdentityNumber`, `k`.`IssuedOn`, `k`.`CreatedOn`, `k`.`ExpireOn`, `k`.`DocumentUrl`, `k`.`Status`, `k`.`SubType`
FROM `KYCDocument` AS `k`
WHERE NOT (`k`.`IsDeleted`) AND ((`k`.`CreatedBy` = @__query_UserId_0) AND (`k`.`Status` <> -1))

仓储继承的AuditableEntity设置了全局查询过滤器:

builder.HasQueryFilter(a => !a.IsDeleted);

需求目标

非客户角色(如管理员)查询时,需忽略全局过滤器,能查看所有文档(包括已删除的),仅排除状态为UploadInProgress的文档。

核心问题

传入ignoreFilters: true后,全局过滤器未被忽略,SQL仍保留NOT (k.IsDeleted)条件。即使改用测试代码(如下),问题依旧:

var kycDocs = await _kycDocRepo.GetAllAsync(a => a.CreatedBy == query.UserId &&
             (query.Profile.Role == UserRoleName.Customer ? (a.Status == KYCDocumentStatus.Approved) : true),
            
             ignoreFilters: ignoreQueryFilters,
             select: a => new CustomerIdentityItemDTO
             {
                 Id = a.Id,
                 Type = a.Type,
                 IdentityNumber = a.IdentityNumber,
                 IssuedOn = a.IssuedOn,
                 CreatedOn = a.CreatedOn,
                 ExpireOn = a.ExpireOn,
                 DocumentUrl = a.DocumentUrl,
                 Status = a.Status,
                 SubType = a.SubType,
                 ExpiryStatus = CustomerHelpers.GetDocumentValidityStatus(a.Type, a.ExpireOn)
             });

仓储层GetAllAsync方法实现

public async Task<IQueryable<T>> GetAllAsync(Expression<Func<T, bool>> filter, bool ignoreFilters = false, Expression<Func<T, object>> includeProperties = null, string includePropertiesAsString = null)
 {
     var entity = includeProperties != null ? LoadNavigationProperties(Entity, includeProperties) : LoadNavigationProperties(Entity, includePropertiesAsString);
     if (ignoreFilters)
     {
         entity.IgnoreQueryFilters();
     }

     return await Task.FromResult(entity.Where(filter).AsQueryable<T>());
 }

问题原因与修复

问题出在GetAllAsync方法中:EF Core的IgnoreQueryFilters()方法是返回一个新的IQueryable实例,而非修改原对象。原代码仅调用entity.IgnoreQueryFilters()但未将返回值赋值给entity,导致全局过滤器未被真正忽略。

修改后的GetAllAsync方法:

public async Task<IQueryable<T>> GetAllAsync(Expression<Func<T, bool>> filter, bool ignoreFilters = false, Expression<Func<T, object>> includeProperties = null, string includePropertiesAsString = null)
 {
     var entity = includeProperties != null ? LoadNavigationProperties(Entity, includeProperties) : LoadNavigationProperties(Entity, includePropertiesAsString);
     if (ignoreFilters)
     {
         // 关键:将IgnoreQueryFilters的返回值重新赋值给entity
         entity = entity.IgnoreQueryFilters();
     }

     return await Task.FromResult(entity.Where(filter).AsQueryable<T>());
 }

修改后,当ignoreFilters为true时,全局过滤器会被正确忽略,生成的SQL将不再包含NOT (k.IsDeleted)条件,管理员即可查询到已删除的文档。

内容的提问来源于stack exchange,提问作者Azubuike Okolie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 06:12:33