【问题标题】:How to Conditionally the column in LINQ OrderByDescending for OrderBy?如何在 C# 中为 OrderBy 有条件地设置 LINQ OrderByDescending 中的列?
【发布时间】:2020-03-26 15:07:18
【问题描述】:

如何使用 LINQ OrderBy 子句有条件地对列进行排序。

ex-我有一个属性 Filter.OrderByFilter.Order 。在OrderBy 中可能有很多 ex>姓名、地址、城市等,Order 将升序或降序,但我不确定如何使用条件列对其进行排序

请参考以下代码-

IQueryable<Filter> query;

PropertyInfo prop = typeof(Filter).GetProperty(Filter.OrderBy);  

if (Filter.Order ==" Ascending"){
  query = query.OrderBy ( x = > prop.GetValue(x,null));
}
else if (Filter.Order ==" Descending"){
  query = query.OrderByDescending ( x = > prop.GetValue(x,null));
}

但查询失败。我不确定是什么问题我可以使用反射看到 prop 属性 但表达式 prop.GetValue 不起作用。

请帮我解决这个问题

【问题讨论】:

  • 你遇到了什么错误?
  • @dcg 查询无法使用 query.OrderBy 列找到排序似乎我无法动态更改属性 ex - x => x.Address 等
  • 所以query.OrderBy(x =&gt; x.Address) 不起作用?
  • 这能回答你的问题吗? c# use string parameter to define what property to filter by in List of objects - 虽然这是一个Where 子句,但应该很容易适应OrderBy
  • 顺便说一句,您正在与" Ascending"" Descending"(带前导空格)进行比较,对吗?否则你永远不会编写 OrderBy 查询。

标签: c# .net entity-framework linq dynamic-linq


【解决方案1】:

您可以使用库System.Linq.Dynamic.Core,它支持动态查询、选择和排序。

示例代码:

var q = new List<Person>
{
    new Person{Name = "C", Age = 30 },
    new Person{Name = "A", Age = 7 },
    new Person{Name = "B", Age = 5 }
}.AsQueryable();

var x1 = q.OrderBy("Name asc");

var a1 = q.OrderBy("Age desc");

有关完整的工作示例,请参阅dotnetfiddle

【讨论】:

  • 这个解决方案对我有用,而且很容易实现谢谢@Stef Heyenrath
【解决方案2】:

我创建了这个示例,也许它可以帮助你

IEnumerable<Person> q = new List<Person>
{
    new Person{Name = "C", Age = 3 },
    new Person{Name = "A", Age = 7 },
    new Person{Name = "B", Age = 5 }
};
var props = new[] { "Name", "Age" };
var orders = new[] { "Ascending", "Descending" };

foreach (var prop in props)
{
    var property = typeof(Person).GetProperty(prop);
    foreach (var order in orders)
    {
        IEnumerable<Person> q2 = null;
        if (order == "Ascending")
        { q2 = q.OrderBy(p => property.GetValue(p)); }
        else
        { q2 = q.OrderByDescending(p => property.GetValue(p)); }

        Console.WriteLine("Property: {0}, Order: {1}", prop, order);
        foreach (var p in q2)
        {
            Console.WriteLine("Name: {0}, Age: {1}", p.Name, p.Age);
        }
        Console.WriteLine();
    }
}

输出:

Property: Name, Order: Ascending
Name: A, Age: 7
Name: B, Age: 5
Name: C, Age: 3

Property: Name, Order: Descending
Name: C, Age: 3
Name: B, Age: 5
Name: A, Age: 7

Property: Age, Order: Ascending
Name: C, Age: 3
Name: B, Age: 5
Name: A, Age: 7

Property: Age, Order: Descending
Name: A, Age: 7
Name: B, Age: 5
Name: C, Age: 3

【讨论】:

    【解决方案3】:

    将属性设置为参数。 示例:

    var param = "Address";    
    var propertyInfo = typeof(Filter).GetProperty(param);    
    var orderByAddress = items.OrderBy(x => propertyInfo.GetValue(x, null));
    

    【讨论】:

      【解决方案4】:
      public static class LinqUtils
          {
              /// <summary>
              /// Orders the by.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="source">The source.</param>
              /// <param name="propertyName">Name of the property.</param>
              /// <param name="direction">The direction.</param>
              /// <returns></returns>
              public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName, OrderDirection direction)
              {
                  switch (direction)
                  {
                      case OrderDirection.ASC:
                          return source.OrderBy(ToLambda<T>(propertyName));
      
                      case OrderDirection.DESC:
                          return source.OrderByDescending(ToLambda<T>(propertyName));
      
                      default:
                          return source.OrderBy(ToLambda<T>(propertyName));
                  }
      
              }
      
              /// <summary>
              /// Orders the by.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="source">The source.</param>
              /// <param name="propertyName">Name of the property.</param>
              /// <param name="direction">The direction.</param>
              /// <returns></returns>
              public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName, int direction)
              {
                  var dir = (OrderDirection)direction;
      
                  switch (dir)
                  {
                      case OrderDirection.ASC:
                          return source.OrderBy(ToLambda<T>(propertyName));
      
                      case OrderDirection.DESC:
                          return source.OrderByDescending(ToLambda<T>(propertyName));
      
                      default:
                          return source.OrderBy(ToLambda<T>(propertyName));
                  }
      
              }
      
      
              /// <summary>
              /// Orders the by.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="source">The source.</param>
              /// <param name="propertyName">Name of the property.</param>
              /// <returns></returns>
              public static IOrderedMongoQueryable<T> OrderBy<T>(this IMongoQueryable<T> source, string propertyName)
              {
                  return source.OrderBy(ToLambda<T>(propertyName));
              }
      
              /// <summary>
              /// Orders the by descending.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="source">The source.</param>
              /// <param name="propertyName">Name of the property.</param>
              /// <returns></returns>
              public static IOrderedMongoQueryable<T> OrderByDescending<T>(this IMongoQueryable<T> source, string propertyName)
              {
                  return source.OrderByDescending(ToLambda<T>(propertyName));
              }
      
              /// <summary>
              /// Wheres the specified property name.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="source">The source.</param>
              /// <param name="propertyName">Name of the property.</param>
              /// <param name="stringToSource">The string to source.</param>
              /// <returns></returns>
              public static IMongoQueryable<T> Where<T>(this IMongoQueryable<T> source, string propertyName, string stringToSource)
              {
                  return source.Where(ToLambdaWhere<T>(propertyName, stringToSource));
              }
      
      
              /// <summary>
              /// Wheres the text.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="query">The query.</param>
              /// <param name="field">The field.</param>
              /// <param name="search">The search.</param>
              /// <returns></returns>
              public static IMongoQueryable<T> WhereText<T>(this IMongoQueryable<T> query, Expression<Func<T, object>> field, string search)
              {
      
                  search = Regex.Escape(search);
                  var filter = Builders<T>.Filter.Text(search);
                  var member = HelpersLinq.PropertyName<T>(field);
      
                  var regexFilter = string.Format("^{0}.*", search);
                  var filterRegex = Builders<T>.Filter.Regex(member, BsonRegularExpression.Create(new Regex(regexFilter, RegexOptions.IgnoreCase)));
      
                  return query.Where(_ => filter.Inject() && filterRegex.Inject());
              }
      
              /// <summary>
              /// Converts to lambda.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="propertyName">Name of the property.</param>
              /// <returns></returns>
              private static Expression<Func<T, object>> ToLambda<T>(string propertyName)
              {
                  var parameter = Expression.Parameter(typeof(T));
                  var property = Expression.Property(parameter, propertyName);
                  var propAsObject = Expression.Convert(property, typeof(object));
      
                  return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
              }
      
              /// <summary>
              /// Converts to lambdawhere.
              /// </summary>
              /// <typeparam name="T"></typeparam>
              /// <param name="propertyName">Name of the property.</param>
              /// <param name="stringToSearch">The string to search.</param>
              /// <returns></returns>
              private static Expression<Func<T, bool>> ToLambdaWhere<T>(string propertyName, string stringToSearch)
              {
                  //var parameter = Expression.Parameter(typeof(T));
      
                  // Create a parameter to use for both of the expression bodies.
                  var parameter = Expression.Parameter(typeof(T), "x");
                  // Invoke each expression with the new parameter, and combine the expression bodies with OR.
                  var predicate = Expression.Lambda<Func<T, bool>>(Expression.Call(Expression.PropertyOrField(parameter, propertyName), "Contains", null, Expression.Constant(stringToSearch)), parameter);
      
                  return predicate;
              }
          }
      
      
          public static class HelpersLinq
          {
              public static string PropertyName<T>(Expression<Func<T, object>> expression)
              {
                  var member = expression.Body as MemberExpression;
                  if (member != null && member.Member is PropertyInfo)
                      return member.Member.Name;
      
                  throw new ArgumentException("Expression is not a Property", "expression");
              }
          }
      
      public enum OrderDirection
      {
          ASC = 1,
          DESC
      }
      

      所以你可以像这样使用它:

       initialQuery.OrderBy("Name", OrderDirection.ASC)
      

      希望对你有帮助!

      【讨论】:

        猜你喜欢
        • 2017-12-25
        • 1970-01-01
        • 2019-10-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多