Linq Sort Direction From String

2019-06-18 05:22发布

I am trying to sort a set of Users. I have access to the sorting property and direction (asc, desc). My current order by query is below. But as you can see it doesn't account for the sort direction. How do can I build this expression without having to use Dynamic Linq, or adding another set of statements for "asc" or "desc" sort direction.

public override IQueryable<DalLinq.User> GetSort(IQueryable<DalLinq.User> query) 
{
    //SelectArgs.SortDirection <- Sort Direction
    switch (SelectArgs.SortProperty) 
    {
      case "LastName":
        query = query.OrderBy(p => p.LastName);
        break;
      case "FirstName":
        query = query.OrderBy(p => p.FirstName);
        break;
      default:
        query = query.OrderBy(p => p.UserName);
        break;
    } 

    return query;
}

3条回答
疯言疯语
2楼-- · 2019-06-18 05:31

Have a look at the CS Code Samples. There are a dynamic Linq examples.

From the samples:

Northwind db = new Northwind(connString); 
db.Log = Console.Out;

var query =
  db.Customers.Where("City == @0 and Orders.Count >= @1", "London", 10).
  OrderBy("CompanyName").
  Select("New(CompanyName as Name, Phone)");

Order by Code:

    public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string ordering, params object[] values) {
        return (IQueryable<T>)OrderBy((IQueryable)source, ordering, values);
    }

    public static IQueryable OrderBy(this IQueryable source, string ordering, params object[] values) {
        if (source == null) throw new ArgumentNullException("source");
        if (ordering == null) throw new ArgumentNullException("ordering");
        ParameterExpression[] parameters = new ParameterExpression[] {
            Expression.Parameter(source.ElementType, "") };
        ExpressionParser parser = new ExpressionParser(parameters, ordering, values);
        IEnumerable<DynamicOrdering> orderings = parser.ParseOrdering();
        Expression queryExpr = source.Expression;
        string methodAsc = "OrderBy";
        string methodDesc = "OrderByDescending";
        foreach (DynamicOrdering o in orderings) {
            queryExpr = Expression.Call(
                typeof(Queryable), o.Ascending ? methodAsc : methodDesc,
                new Type[] { source.ElementType, o.Selector.Type },
                queryExpr, Expression.Quote(Expression.Lambda(o.Selector, parameters)));
            methodAsc = "ThenBy";
            methodDesc = "ThenByDescending";
        }
        return source.Provider.CreateQuery(queryExpr);
    }

But be sure that you check User Input!

查看更多
疯言疯语
3楼-- · 2019-06-18 05:38

Ideally, you want to use OrderByDescending - you could of course cheat:

public static class MyExtensionMethods 
{
    public static IOrderedQueryable<TSource> OrderBy<TSource,TValue>(
        this IQueryable<TSource> source,
        Expression<Func<TSource,TValue>> selector,
        bool asc) 
    {
        return asc ? source.OrderBy(selector) : source.OrderByDescending(selector); 
    }
}

And use OrderBy passing in the selector and a bool?

If you don't need the static typing, you can also build the expressions dynamically from the ground up, of course - like this short sample (similar in nature to the dynamic LINQ library).

查看更多
该账号已被封号
4楼-- · 2019-06-18 05:42

It'd be an if statement I think, no other simple way to do it, i.e.:

query = (SelectArgs.SortDirection == "asc") ? query.OrderBy(p => p.LastName)
          : query.OrderByDescending(p => p.LastName);

Have a look at this as well: Sorting a list using Lambda/Linq to objects

查看更多
登录 后发表回答