1

So I have a function like below which takes in a list of objects and keeps including them into my query string. This works great.

query = includeExpressions.Aggregate(query, (current, include) => current.Include(include));

But what I am wanting to do is to Aggregate the OrderBys as well. This is where I am running into issues. The issue I have is that one must use OrderBy then use ThenBy on the same line. I've tried using a for loop first item use order by then on use thenby. The issue I am running in is that in order for thenby to be activated the order by needs to proceed it on the same object line.

query.OrderBy(orderBy).ThenBy

I can not do

var usedOrderBy = true;
        foreach (var orderBy in orderBys)
        {
            if (usedOrderBy)
            {
                query = query.OrderBy(orderBy);

                usedOrderBy = true;
            }
            else
            {
                query = query.ThenBy(orderBy); // <-- Can not locate thenby
            }
        }

any ides.

I want to pass in like

orderItems(x => x.Item1, x => x.Item2)
Demodave
  • 6,242
  • 6
  • 43
  • 58
  • 1
    Maybe this will help [Orderby and thenby using LINQ](https://stackoverflow.com/questions/35728983/orderby-and-thenby-using-linq) – Barns Jan 10 '19 at 23:06
  • Remove the `usedOrderBy` and instead have a variable storing the results of the `OrderBy` (I am not sure of the type OTTOMH - probably `IOrderedQueryable`). Then inside the loop, check whether the `variable` is `null` or not (rather than checking the `bool`. – mjwills Jan 10 '19 at 23:17
  • You can visit the expression tree to see if it contains an "OrderBy" method call. – Gert Arnold Jan 11 '19 at 08:21

3 Answers3

2

The problem is in the type of query variable. ThenBy is the extension method that can be applied to System.Linq.IOrderedEnumerable<TSource> or System.Linq.IOrderedQueryable<TSource> so you can't do just

IEnumerable<Point> points = GetPoints();
points = points.OrderBy(p => p.X);
points = points.ThenBy(p => p.Y);

You should have an extra variable for preordered result to solve your scenario like in an example below:

IEnumerable<Point> points = GetPoints();
var orderedPoints = points.OrderBy(p => p.X);
orderedPoints = orderedPoints.ThenBy(p => p.Y);
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
Vadim Martynov
  • 8,602
  • 5
  • 31
  • 43
0

Check this

   var orderByList = new List<Expression<Func<TEntity, object>>>();
            Expression<Func<TEntity,object>> orderBy1 = x => x.Id;
            Expression<Func<TEntity, object>> orderBy2 = x => x.ToString();
            Expression<Func<TEntity, object>> orderBy3 = x => x.Id;
            orderByList.Add(orderBy1);
            orderByList.Add(orderBy2);
            orderByList.Add(orderBy3);

            var resultOrderedQueryable = orderByList.Aggregate<Expression<Func<TEntity, object>>, IOrderedQueryable<TEntity>>(null, (current, orderBy) => current != null ? current.ThenBy(orderBy) : query.OrderBy(orderBy));
Demodave
  • 6,242
  • 6
  • 43
  • 58
NaDeR Star
  • 647
  • 1
  • 6
  • 13
0

Your query will work if can have initial seed of OrderBy. Then you can chain ThenBy's. As mentioned, ThenBy requires an IOrderedEnumerable (or IOrderedQueryable) first before attaching ThenBy clauses:

Your code will look like below:

IOrderedQueryable<T> orderedQuery = null;
for(int temp = 0; temp < orderBys.Count; temp++)
{
    if(temp == 0)
        orderedQuery = query.OrderBy(orderBys[temp]);

    else orderedQuery = orderedQuery.ThenBy(orderBys[temp]);  
}
query = orderedQuery ?? query;

Reference: How to generate a dynamic number of ThenBy clauses in a Specification

Gauravsa
  • 6,330
  • 2
  • 21
  • 30