.NET Core 3.1中对含空值的IQueryable执行OrderBy操作报错如何解决
根因分析
- 你当前的
IsDiscountedProductsByGroups方法完全不符合IQueryable的使用规范:直接遍历IQueryable会立即触发数据库查询,把所有初始数据加载到内存,后续排序、过滤操作都只能在内存执行,性能极差。 - 该方法里你使用的
Append不会修改原集合,且如果listDiscountedProductsByGroup是全局变量还会有线程安全问题,当没有符合条件的折扣商品时,返回的集合为空、类型也不是EF Core可跟踪的IQueryable类型,后续执行OrderBy操作时就会触发异常。 - 若排序字段存在空值,没有空值兜底逻辑也会引发空引用报错。
解决方案
1. 重构折扣过滤方法
直接基于IQueryable拼接Where条件,所有逻辑会转成SQL在数据库侧执行,既提升性能也不会破坏IQueryable的类型结构:
public IQueryable<Group> IsDiscountedProductsByGroups(IQueryable<Group> groups) { var now = DateTime.Now; return groups.Where(p => p.Product.PurchasePrice != null && p.Product.StartDiscountTime != null && p.Product.StartDiscountTime < now && p.Product.EndDiscountTime != null && p.Product.EndDiscountTime > now); }
2. 排序增加空值兜底逻辑
如果排序字段存在为空的可能,在排序规则里增加空值判断,避免空引用异常:
case "lowPrice": { // PurchasePrice为空的商品排在最后,兜底数值可根据业务调整 result = result.OrderBy(p => p.Product.PurchasePrice ?? 999999) // TireDiameter为空的用空字符串兜底 .ThenBy(p => p.Product.TireDiameter != null ? p.Product.TireDiameter.Code : ""); break; } // 其他排序规则按照相同逻辑修改即可
3. 增加空集合兜底判断
所有过滤、排序逻辑执行完成后,先判断集合是否有数据再做后续ViewModel映射,避免空集合操作报错:
if (!result.Any()) { // 直接返回空结果即可,参数根据你的实际返回类型调整 return Tuple.Create(Enumerable.Empty<YourViewModel>(), 0); }
内容的提问来源于stack exchange,提问作者irancss
相关产品推荐
相关产品推荐

