C# 与属性名称匹配的Order By字符串提供空引用

C# 与属性名称匹配的Order By字符串提供空引用,c#,asp.net-mvc,linq,C#,Asp.net Mvc,Linq,我对下面的排序方案有问题 var model = DbContext .Select(s => new ViewModel) .OrderBy(paging.Sorting); paging.Sorting是一个来自客户端的字符串,从不为空。 如果列具有空值,则排序将引发空引用异常。 有没有办法使用lamdba表达式 这是我经常遇到的一个错误,我正试图找到一个解决方案 例如: var people = DbContext.People

我对下面的排序方案有问题

var model = DbContext
           .Select(s => new ViewModel)
           .OrderBy(paging.Sorting);
paging.Sorting是一个来自客户端的字符串,从不为空。

如果列具有空值,则排序将引发空引用异常。

有没有办法使用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异常。

我尝试用下面的代码段复制它,它工作得非常好,您能分享有关错误或代码段的更多详细信息吗

using System.Linq.Dynamic;

    List<customobj> items = new List<customobj> {
                new customobj{num=1,text="Ab"},
                new customobj{num=2},
                new customobj{num=3,text="cc"},
                new customobj{num=4,text="dd"},
                new customobj{num=5,text="ee"},
            };
            var item = items.AsQueryable().OrderBy("text DESC");
使用System.Linq.Dynamic;
列表项=新列表{
新建customobj{num=1,text=“Ab”},
新customobj{num=2},
新建customobj{num=3,text=“cc”},
新customobj{num=4,text=“dd”},
新customobj{num=5,text=“ee”},
};
var item=items.AsQueryable().OrderBy(“文本描述”);

按属性名称排序,无类型反射

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
                 ));
      }
}
或者您可以使用类型反射(不使用IQueryableExtensions)(尽管它不是很有效):如下

var people = DbContext.People
                      .Select(p => new PersonViewModel{
                      Name = p.Name,
                      ManagerId = p.ManagerId,
                      DepartmentId = p.DepartmentId
                      })
                      .OrderBy(paging.Sorting)
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))

如果ManagerId为空,您是否可以执行内联检查并为订单设置“默认”回退

比如说:

string defaultOrder = "DepartmentId DESC";

var people = DbContext.People
    .Select(p => new PersonViewModel{
        Name = p.Name,
        ManagerId = p.ManagerId,
        DepartmentId = p.DepartmentId
    })
    .OrderBy(p => (paging.Sorting.ToLower().Contains("managerid") && p.ManagerId == null) ? defaultOrder : paging.Sorting)

我刚刚很快就完成了这项工作,所以请原谅任何打字错误

您可以通过检查分页来处理此问题。排序如果为空,则传递默认排序键您的代码包含错误。请向我们提供必要的信息以分析问题。例如:使用
newviewmodel
,您真正选择的是什么。如果没有更多信息,就不可能回答您的问题。@Prasadelkikikar paging.Sorting从不为空。@RonyPatel paging.Sorting从不为空。@kurdy
ManagerId
不太可能是
字符串(我想说可能是
int
),但无论如何,您的代码应该是
ManagerId=p.ManagerId!=无效的p、 ManagerId:“
(带三元运算符)或
ManagerId=p.ManagerId??“”
(使用空合并运算符)嗯,您使用了
OrderBy(x=>x.text)
。您是否按照OP的建议尝试使用了
OrderBy(“text DESC”)
?您正在编写的代码使用的是Lambdas。我的代码使用字符串排序。此外,我正在查询数据库。请查看我的示例。我在发布此答案时没有看到更新的代码,我将对其进行更新,但我无法将其作为评论发布。。将使用linq dynamic检查它,并检查它是否工作正常var item=items.AsQueryable().OrderBy(“text DESC”)@panoskarajohn您是否尝试过linq.dynamic,它不需要lambda表达式来指定按列排序的顺序?您的做法是正确的。但是paging.Sorting值是“ManagerId ASC”“ManagerId DESC”@panoskarajohn您可以让客户端在不同的参数中发送ASC或DESC,并基于它您可以使用(OrderBy(),OrderByDescending())我知道我可以解决这个问题。我使用了.Split()使您的解决方案有效。我有大约一百万个属性。这是一个小规模solurion的解决方案。请参阅Musab.BA的答案。他在正确的轨道上。好的,没关系。你的行动中没有暗示问题的严重性。