使用Ardalis.Specification 5.1.0基于LINQ查询CosmosDB返回null问题
问题根因
你遇到的null返回问题源于Ardalis.Specification 5.x版本的默认Evaluate方法设计:该方法默认会直接执行传入的IQueryable并返回物化后的实体集合,而非返回拼接了规约条件的IQueryable实例,因此你将执行结果强转为IQueryable<T>时自然得到空值。
可行修复方案
无需额外依赖包,只需替换Evaluate调用逻辑,手动将规约中定义的查询条件应用到CosmosDB原生的IQueryable上即可,修改后的代码如下:
public async IAsyncEnumerable<T> GetItemsAsyncEnumerable(ISpecification<T> specification) { // 初始化CosmosDB原生LINQ查询对象 IQueryable<T> query = _container.GetItemLinqQueryable<T>(); // 应用查询条件 if (specification.Criteria != null) { query = query.Where(specification.Criteria); } // 应用排序规则 foreach (var orderExp in specification.OrderExpressions) { query = orderExp.OrderType switch { OrderType.OrderBy => query.OrderBy(orderExp.KeySelector), OrderType.OrderByDescending => query.OrderByDescending(orderExp.KeySelector), OrderType.ThenBy => ((IOrderedQueryable<T>)query).ThenBy(orderExp.KeySelector), OrderType.ThenByDescending => ((IOrderedQueryable<T>)query).ThenByDescending(orderExp.KeySelector), _ => query }; } // 应用分页规则 if (specification.Skip.HasValue) query = query.Skip(specification.Skip.Value); if (specification.Take.HasValue) query = query.Take(specification.Take.Value); // 执行查询 using var iterator = query.ToFeedIterator<T>(); while (iterator.HasMoreResults) { var response = await iterator.ReadNextAsync(); foreach (var item in response) { yield return item; } } }
可选优化
如果你需要复用更多Ardalis.Specification的内置能力,可以升级到6.x及以上版本,该版本提供了专门的IQueryable拓展方法WithSpecification,可以直接将规约应用到查询对象上,无需手动拼接条件。
你现有的FooFromIdSpecification定义符合规范,无需修改。
内容的提问来源于stack exchange,提问作者Ruskin
相关产品推荐
相关产品推荐

