c# - 处理请求时发生未处理的异常。(asp.net 上的 Rest api 排序)
问题描述
InvalidOperationException:无法翻译 LINQ 表达式“DbSet().OrderBy(s => s.GetType().GetProperty(__sort_by_0).GetValue(s))”。以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。有关详细信息,请参阅https://go.microsoft.com/fwlink/?linkid=2101038。
当我尝试按属性对我的 rest api 进行排序时,会发生此错误。在此处输入图像描述
解决方案
有人在评论中链接了以前的答案,这让我不确定我是否应该回答这个问题,但是,它已经写好了。:)
基本上动态排序比您尝试做的要复杂一些。那GetType()
, GetProperty()
, 等反射代码不能在数据库中执行。
你基本上有两个选择:
1) 使用动态 Linq 包
使用System.Linq.Dynamic.Core
包(请参阅文档),您可以提供对实体成员的字符串引用,并将其转换为表达式。
这意味着你可以简单地写这个:
_context.SwiftTransfers.OrderBy(sort_by).ToListAsync();
2) 使用自定义解决方案将字符串转换为表达式
您可以自己构建表达式。例如,以下方法支持IQueryable
根据提供的字符串成员名称(可以引用具有“用户/名称/名字”模式的嵌套属性)对 应用多个升序或降序:
static IQueryable<T> ApplyOrdering(IQueryable<T> query, string propertyPath, bool isAscending = true, bool firstOrdering = true)
{
var param = Expression.Parameter(typeof(T), "p");
var member = (MemberExpression)propertyPath.Split('/').Aggregate((Expression)param, Expression.Property);
var exp = Expression.Lambda(member, param);
string methodName = isAscending switch
{
true => firstOrdering ? "OrderBy" : "ThenBy",
false => firstOrdering ? "OrderByDescending" : "ThenByDescending"
};
Type[] types = new Type[] { query.ElementType, exp.Body.Type };
var orderByExpression = Expression.Call(typeof(Queryable), methodName, types, query.Expression, exp);
return query.Provider.CreateQuery<T>(orderByExpression);
}
// Then call it like this:
ApplyOrdering(_context.SwiftTransfers.AsQueryable(), sort_by).ToListAsync();
这可以用作扩展方法IQueryable
以更舒适地访问它。
提示
如果您想实现符合标准的排序/过滤方式,您可以查看OData。它有现成的包,你可以在 ASP.NET Core 的端点上应用。不过,我个人不太喜欢他们的实施建议,因此我通常手动实施符合 OData 的过滤和排序。
如果您使用更改数据形状的 DTO,并且客户端将根据 DTO 向您发送排序参数,您可能会遇到给定属性名称在您尝试排序的实际实体上不存在的问题. 但是,如果您使用 AutoMapper 进行映射,并且如果您映射 via
ProjectTo<TDto>()
,则会自动将表达式转换回来,以便它们引用正确的实体属性。因此,您不必手动进行属性名称映射。
推荐阅读
- scala - 如何为以下只有一列的数据创建表
- powerbi - Power BI - 根据条件提取数据
- android - 如何从 github 运行这个 android studio 应用程序?
- java - 并行编写多个 parquet 文件
- python - Python:基于一个特定键相同的所有dict键值组合
- javascript - 外部化一个 setTimeout 函数
- jquery - 将 onChange 与 yadcf 下拉选择一起使用
- flutter - Dart 在 pubspec.yaml 中为多模块项目使用任何依赖项
- html - ReactJS 中的多级菜单
- java - 在使用 Apache Lucene 7.1.0 的 JapaneseTokenizer 时遇到 NoClassDefFoundError