如何在EF中基于字符串参数动态构建带过滤条件的Include查询
问题原因
- 调用
Queryable.Where时参数顺序传递错误:Queryable.Where扩展方法的第一个入参是待查询的数据源,第二个才是过滤谓词,原代码中两个参数顺序颠倒,导致方法匹配失败 - 导航属性的默认类型是
ICollection<T>(属于IEnumerable<T>),不能直接作为IQueryable<T>类型传入Queryable.Where,需要调用适配IEnumerable的Enumerable.Where方法
修复后的实现代码
using System.Linq.Dynamic.Core; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore; public static class QueryableExtensions { public static IQueryable<T> DynamicIncludeWithFilter<T>(this IQueryable<T> queryable, string includeField, string filterExpression) where T : class { // 校验导航属性是否存在 var navigationProp = typeof(T).GetProperty(includeField); if (navigationProp == null) throw new ArgumentException($"类型{typeof(T).Name}中不存在名为{includeField}的属性"); // 获取导航集合的元素类型 var elementType = navigationProp.PropertyType.GetGenericArguments().FirstOrDefault(); if (elementType == null) throw new ArgumentException($"属性{includeField}不是泛型集合类型,无法添加过滤条件"); // 构建表达式参数 x => ... var parameter = Expression.Parameter(typeof(T), "x"); var propertyAccess = Expression.Property(parameter, navigationProp); // 解析字符串格式的过滤条件为谓词表达式 var predicate = DynamicExpressionParser.ParseLambda(ParsingConfig.Default, elementType, typeof(bool), filterExpression); // 调用Enumerable.Where方法,参数顺序:[数据源, 过滤谓词] var whereCallExpr = Expression.Call( typeof(Enumerable), nameof(Enumerable.Where), new[] { elementType }, propertyAccess, predicate ); // 生成Include方法需要的Lambda表达式 var includeLambda = Expression.Lambda<Func<T, object>>(whereCallExpr, parameter); return queryable.Include(includeLambda); } }
调用示例
// 对应你原参考写法的动态调用效果 var result = contextEF.Table1 .DynamicIncludeWithFilter("Field1", "c => c.Id == 500") .ToList();
内容的提问来源于stack exchange,提问作者Uka4me
相关产品推荐
相关产品推荐

