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
相关产品推荐
相关产品推荐

