c# - 与属性名称匹配的按字符串排序给出空引用
问题描述
我对以下排序方案有疑问。
var model = DbContext
.Select(s => new ViewModel)
.OrderBy(paging.Sorting);
paging.Sorting 是来自客户端的字符串,从不为 NULL。
如果列具有空值,则排序将引发空引用异常。
有没有办法使用 lamdba 表达式?
这是我经常遇到的错误,我正在尝试找到一个可靠的解决方案。
例子:
var people = DbContext.People
.Select(p => new PersonViewModel{
Name = p.Name,
ManagerId = p.ManagerId,
DepartmentId = p.DepartmentId
})
.OrderBy(paging.Sorting)
有时 paging.Sorting = "DepartmentId DESC"
或者
paging.Sorting = "ManagerId ASC"
有些人没有经理,并且 Id 的值为空。所以排序会抛出一个 null ref 异常。
解决方案
按属性名称排序,没有类型反射
public static class IQueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string
propertyName)
{
return (IQueryable<T>)OrderBy((IQueryable)source, propertyName);
}
public static IQueryable OrderBy(this IQueryable source, string propertyName)
{
var x = Expression.Parameter(source.ElementType, "x");
var body = propertyName.Split('.').Aggregate<string, Expression>(x,
Expression.PropertyOrField);
var selector = Expression.Lambda
(Expression.PropertyOrField(x, propertyName), x);
return source.Provider.CreateQuery(
Expression.Call(typeof(Queryable), "OrderBy", new Type[] {
source.ElementType, selector.Body.Type },
source.Expression, selector
));
}
public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> source,
string propertyName)
{
return (IQueryable<T>)OrderByDescending((IQueryable)source, propertyName);
}
public static IQueryable OrderByDescending(this IQueryable source, string
propertyName)
{
var x = Expression.Parameter(source.ElementType, "x");
var selector = Expression.Lambda(Expression.PropertyOrField(x,
propertyName),x);
return source.Provider.CreateQuery(
Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] {
source.ElementType, selector.Body.Type },
source.Expression, selector
));
}
}
那么你可以像这样使用它
var people = DbContext.People
.Select(p => new PersonViewModel{
Name = p.Name,
ManagerId = p.ManagerId,
DepartmentId = p.DepartmentId
})
.OrderBy(paging.Sorting)
或者你可以使用类型反射(没有 IQueryableExtensions)来做到这一点(虽然它不是很有效):像这样
var people = DbContext.People
.Select(p => new PersonViewModel{
Name = p.Name,
ManagerId = p.ManagerId,
DepartmentId = p.DepartmentId
})
.OrderBy(o => o.GetType()
.GetProperty(paging.Sorting)
.GetValue(o, null))
推荐阅读
- python - 按单词应用'for'循环
- javascript - 网站页面需要一段时间才能加载图像
- java - 为什么通过python调用我的api会给出无效的日期格式,而在java中却没有(使用相同的字符串)
- sql - 如何在 Oracle 上对多个表上的插入进行排序,以便不破坏 FK 约束
- azure-ad-b2c - 如何更改 azure ad b2c 自定义策略中自断言步骤的最大重试次数
- javascript - 将变量值分配给锚标记以创建超链接
- matlab - 在 Matlab 中从一维数组创建多维数组?
- python - 从 VSCode 运行时尝试通过 Selenium 打开 Firefox 失败
- prolog - 天真的假设被认为是有害的:带有累加器的 Prolog 谓词打击(全局)堆栈,但天真的版本没有
- git - asciidoc:失败:缺少配置文件 asciidoc.conf