如何在Dynamic LINQ中用Contains替代多OR条件的字符串查询?
可行方案及实现方式
完全可以改用Contains方法生成查询字符串,这样生成的表达式更简洁,多数ORM(比如EF)还能将其优化为IN查询,性能比多OR条件更优。
修改后的实现代码
直接修改BuildWhereClause方法,生成调用Contains的表达式字符串即可,同时要处理不同数据类型的值(比如字符串需用双引号包裹):
string BuildWhereClause(string fieldName, List<object> values) { // 格式化值:字符串类型转义后加双引号,数值/布尔等类型直接转字符串 var formattedValues = values.Select(value => value is string str ? $"\"{str.Replace("\"", "\\\"")}\"" : value.ToString() ); // 构建值数组的字符串表示,再生成Contains调用表达式 var valuesStr = $"new[] {{ {string.Join(", ", formattedValues)} }}"; return $"x => {valuesStr}.Contains(x.{fieldName})"; }
示例效果
- 当输入字段名
"PropFromUi"、值列表(440, 1126, 661)时,生成的查询字符串为:"x => new[] { 440, 1126, 661 }.Contains(x.PropFromUi)" - 当输入字符串值列表
("Apple", "Banana", "Orange")时,生成的查询字符串为:"x => new[] { \"Apple\", \"Banana\", \"Orange\" }.Contains(x.FruitName)"
修复原代码的小问题
原FilterByUi存在两处错误,修正后才能正常运行:
- 参数
filedName拼写错误,应为fieldName - LINQ的
Where方法返回新查询对象,需赋值回原变量
修正后的FilterByUi:
IQueryable FilterByUi(IQueryable query, string fieldName, List<object> values) { string whereClause = BuildWhereClause(fieldName, values); query = query.Where(whereClause); return query; }
注意事项
- 如果值列表为空,生成的
Contains表达式会返回false,可根据业务需求添加判断,比如空列表时直接返回原查询 - 对于枚举、DateTime等复杂类型,需额外处理值的格式化,确保表达式语法正确
内容的提问来源于stack exchange,提问作者Sam Carleton
相关产品推荐
相关产品推荐

