EF Core 如何通过传入的属性名字符串动态构造可翻译的查询条件
错误原因
你原来的写法无法生效是因为prop.GetValue(x)是反射方法调用,EF Core的查询转换器无法将这类运行时反射操作翻译成SQL语句,放在IQueryable查询链中调用时就会触发无法翻译的异常。
解决方案
通过动态构造表达式树的方式实现,生成EF Core可识别的查询逻辑,无需拼接原生SQL。
第一步:编写通用扩展方法
using System.Linq.Expressions; public static class QueryableExtensions { /// <summary> /// 为IQueryable附加指定属性的相等查询条件 /// </summary> /// <typeparam name="T">实体类型</typeparam> /// <param name="query">原始查询对象</param> /// <param name="propertyName">要匹配的属性名</param> /// <param name="searchTerm">搜索值</param> public static IQueryable<T> WherePropertyEquals<T>(this IQueryable<T> query, string propertyName, string searchTerm) { // 构造Lambda参数:x => ... 中的x var parameterExp = Expression.Parameter(typeof(T), "x"); // 构造属性访问:x.PropertyName var propertyExp = Expression.Property(parameterExp, propertyName); // 构造搜索值常量,如需支持非string属性可在此处添加类型转换逻辑 var constantExp = Expression.Constant(searchTerm, typeof(string)); // 构造相等比较表达式:x.PropertyName == searchTerm var equalExp = Expression.Equal(propertyExp, constantExp); // 生成可传入Where的Lambda表达式 var filterLambda = Expression.Lambda<Func<T, bool>>(equalExp, parameterExp); return query.Where(filterLambda); } }
第二步:调用扩展方法实现查询
如果有多个search对象,循环叠加查询条件即可:
// 假设searchList是客户端传入的多个搜索条件集合 foreach(var search in searchList) { query = query.WherePropertyEquals(search.Property, search.SearchTerm); } // 执行查询 var result = query.ToList();
扩展适配场景
- 支持非string类型属性:构造常量前把搜索词转换为属性的实际类型即可
var convertedValue = Convert.ChangeType(searchTerm, propertyExp.Type); var constantExp = Expression.Constant(convertedValue, propertyExp.Type); - 支持模糊查询:将相等比较替换为
Contains方法调用即可var containsMethod = typeof(string).GetMethod("Contains", new[] { typeof(string) }); var containsExp = Expression.Call(propertyExp, containsMethod, constantExp); var filterLambda = Expression.Lambda<Func<T, bool>>(containsExp, parameterExp);
内容的提问来源于stack exchange,提问作者Niall Walker
相关产品推荐
相关产品推荐

