如何在LINQ的Where子句中传递Func表达式实现服务端数据过滤
问题根因
你当前使用的Func<Project, bool>是编译完成的.NET委托,EF Core无法解析委托内部的逻辑将其转换为可在数据库执行的SQL语句,直接调用Invoke执行委托的操作属于客户端运行时逻辑,因此会抛出翻译失败异常。
要实现服务端过滤,必须使用EF Core可解析的Expression<Func<Project, bool>>表达式树,或者直接动态拼接查询条件。
解决方案1:动态拼接IQueryable(推荐)
这种写法可读性高、维护成本低,所有过滤逻辑都会被自动翻译为SQL的WHERE子句,完全在数据库侧执行:
// 构建基础查询 var query = _context.Projects.Where(x => !x.IsDeleted) .Include(pc => pc.ProjectComments.Where(x => !x.IsDeleted)) .Include(sp => sp.SharedProjects) .AsNoTracking(); // 按需追加过滤条件 if (CreatorId != 0) { query = query.Where(f => f.CreatedBy == CreatorId); } if (VerticalMarketId != 0) { query = query.Where(f => f.VerticalMarketsId == VerticalMarketId); } if (ProductCategoryId != 0) { query = query.Where(f => f.ProductCategoriesId == ProductCategoryId); } // 执行最终查询 var getProjects = await query.ToListAsync();
解决方案2:封装为统一表达式
如果需要将过滤逻辑封装为独立的表达式复用,可以直接返回Expression类型:
// 构建过滤表达式 Expression<Func<Project, bool>> GetFilter(int creatorId, int verticalMarketId, int productCategoryId) { return f => (creatorId == 0 || f.CreatedBy == creatorId) && (verticalMarketId == 0 || f.VerticalMarketsId == verticalMarketId) && (productCategoryId == 0 || f.ProductCategoriesId == productCategoryId); } // 查询逻辑 var filter = GetFilter(CreatorId, VerticalMarketId, ProductCategoryId); var getProjects = await _context.Projects .Where(x => !x.IsDeleted) .Where(filter) .Include(pc => pc.ProjectComments.Where(x => !x.IsDeleted)) .Include(sp => sp.SharedProjects) .AsNoTracking() .ToListAsync();
内容的提问来源于stack exchange,提问作者Okasha Momin
相关产品推荐
相关产品推荐

