通过属性名字符串对IMongoQueryable排序出现$sort仅允许字段报错如何解决
错误原因
你抛出Only fields are allowed in a $sort.错误的核心原因是:MongoDB的LINQ查询转换器无法解析你在排序表达式中嵌入的反射调用prop.GetValue(t),它只能识别直接访问类属性的表达式树,才能映射成数据库层面的$sort字段配置。
修复方案
我们可以通过动态构建和手写x=>x.属性名完全等价的表达式树来实现动态排序,修改后的代码如下:
首先需要引入依赖命名空间:
using System.Linq.Expressions;
修改后的方法实现:
private static void SetOrderBy(ref IMongoQueryable<Trade> trades, BlazorGridRequest request) { // 先校验排序字段合法性,避免非法字段报错 var prop = typeof(Trade).GetProperty(request.OrderBy); if (prop == null) { // 可以自定义默认排序逻辑,比如按Id倒序 trades = trades.OrderByDescending(t => t.Id); return; } // 1. 构建表达式参数:t => 中的t var parameter = Expression.Parameter(typeof(Trade), "t"); // 2. 构建属性访问表达式:t.属性名 var propertyAccess = Expression.Property(parameter, request.OrderBy); // 3. 构建完整的Lambda表达式:t => t.属性名 var orderLambda = Expression.Lambda(propertyAccess, parameter); // 4. 反射获取对应的OrderBy/OrderByDescending泛型方法 string methodName = request.OrderByDescending ? nameof(Queryable.OrderByDescending) : nameof(Queryable.OrderBy); var orderMethod = typeof(Queryable) .GetMethods() .First(m => m.Name == methodName && m.GetParameters().Length == 2) .MakeGenericMethod(typeof(Trade), propertyAccess.Type); // 5. 执行排序方法并赋值 trades = (IMongoQueryable<Trade>)orderMethod.Invoke(null, new object[] { trades, orderLambda }); }
补充说明
- 动态构建的表达式树和你手写强类型排序表达式的结构完全一致,MongoDB可以正常翻译成对应的数据库排序指令
- 前置的属性校验可以避免传入不存在的字段名导致的运行时错误,你也可以根据业务需求调整非法字段的兜底逻辑
内容的提问来源于stack exchange,提问作者Rafael Wörner
相关产品推荐
相关产品推荐

