如何使用Predicate Builder实现字符串范围查询?
字符串范围查询实现方案(对标日期范围查询逻辑)
问题描述
现有以下可正常处理日期范围查询的表达式,请问如何用相同方式实现字符串范围查询?
附现有代码(含尝试的字符串查询逻辑,但存在问题):
expression = expression.And(x => x.ProductReceivedDate <= options.ProductReceivedDateEnd) .And(x => x.ProductReceivedDate >= options.ProductReceivedDateStart); if (!string.IsNullOrEmpty(options.PlateNumberFrom)) { expression = expression.And(x => x.InventoryNumber.CompareTo(options.PlateNumberFrom) >= string.Compare(x.InventoryNumber, options.PlateNumberFrom)); } if (string.IsNullOrEmpty(options.PlateNumberTo)) options.PlateNumberTo = options.PlateNumberFrom; if (!string.IsNullOrEmpty(options.PlateNumberTo)) { expression = expression.And(x => x.InventoryNumber.CompareTo(options.PlateNumberTo) <= string.Compare(x.InventoryNumber, options.PlateNumberFrom)); }
修正后的实现方案
原字符串查询逻辑存在错误:嵌套调用的string.Compare(x.InventoryNumber, options.PlateNumberFrom)完全多余,且会导致比较逻辑混乱。我们可以直接对标日期查询的>=/<=逻辑,利用字符串CompareTo方法的返回值来实现范围过滤:
string.CompareTo()返回值规则:小于0表示当前字符串小于目标字符串;等于0表示相等;大于0表示当前字符串大于目标字符串- 要实现
InventoryNumber >= PlateNumberFrom,只需判断CompareTo结果 >= 0 - 要实现
InventoryNumber <= PlateNumberTo,只需判断CompareTo结果 <= 0
修正后的代码如下:
// 保留原正确的日期范围查询逻辑 expression = expression.And(x => x.ProductReceivedDate <= options.ProductReceivedDateEnd) .And(x => x.ProductReceivedDate >= options.ProductReceivedDateStart); // 修正后的字符串范围查询逻辑 if (!string.IsNullOrEmpty(options.PlateNumberFrom)) { expression = expression.And(x => x.InventoryNumber.CompareTo(options.PlateNumberFrom) >= 0); } if (string.IsNullOrEmpty(options.PlateNumberTo)) options.PlateNumberTo = options.PlateNumberFrom; if (!string.IsNullOrEmpty(options.PlateNumberTo)) { expression = expression.And(x => x.InventoryNumber.CompareTo(options.PlateNumberTo) <= 0); }
额外说明
如果业务需要忽略大小写、使用特定文化规则进行比较,可以改用string.Compare方法替换CompareTo,示例如下:
// 忽略大小写的起始值过滤 expression = expression.And(x => string.Compare(x.InventoryNumber, options.PlateNumberFrom, StringComparison.OrdinalIgnoreCase) >= 0); // 忽略大小写的结束值过滤 expression = expression.And(x => string.Compare(x.InventoryNumber, options.PlateNumberTo, StringComparison.OrdinalIgnoreCase) <= 0);
内容的提问来源于stack exchange,提问作者Kelvin
相关产品推荐
相关产品推荐

