jrichview
jrichview

Reputation: 390

Simple OData Client - create OrderBy expression at runtime?

Simple OData queries are straightforward if everything is known at compile time. I have learned how to build expressions at runtime for purposes of filtering, but I have not quite figured out how to build an OrderBy expression at runtime?

Example mockup of a query (dynamic filter expression):

var empls = await client.For<MyModel>("MyTable")
                    .Top(request.PageSize)
                    .Skip((request.Page - 1) * request.PageSize)
                    .Filter(filter)
                    .FindEntriesAsync();

If I knew at compile time what order was needed I could add a .OrderBy() clause. But since the user decides the sorting at runtime, I need to build an expression for ordering.

To dynamically build the filter passed above I used ODataExpression<> object. I'm looking for equivalent capability to pass to an order clause (if that exists?).

Upvotes: 1

Views: 1134

Answers (2)

jrichview
jrichview

Reputation: 390

I noticed another OrderBy() overload of the Fluent client interface:

OrderBy(IEnumerable<KeyValuePair<string, bool>> columns);

If you need dynamic multi-level ordering, you can create a List<KeyValuePair<string, bool>> and populate it with KeyValuePair<string, bool> objects where the string is the field specification and the bool is false for ASCENDING and true for DESCENDING sorts.

Just be sure that your string uses the forward slash "/" as the field path separator rather than the period.

Sorting hierarchy will be in the order that you added the KeyValuePairs to the list. So if you want to sort by:

  1. Person.LastName ASC
  2. Person.FirstName ASC
  3. Person.EmployerName DESC

you just add the objects to the list in the above order, as you would expect passing false, false, true for the booleans.

Upvotes: 0

Chris Schaller
Chris Schaller

Reputation: 16669

There is no need to compose and execute the OData request in a single statement. The Simple OData APIs are designed to allow you to selectively build the query to implement your business logic as you go.

The choice between Ascending and Descending needs to be known, as does the name of the column (or columns) you want to sort on, the details of these haven't been provided in the original post so here I will assume that the sortColumn is a string that defines the column the user has selected and sortDescending is a flag that indicates if the sort direction is in Ascending (false) or Descending (True) order.

var query = client.For<MyModel>("MyTable")
                  .Top(request.PageSize)
                  .Skip((request.Page - 1) * request.PageSize)
                  .Filter(filter);
if (sortDescending)
    query = query.OrderByDescending(sortColumn);
else
    query = query.OrderBy(sortColumn);

var empls = await query.FindEntriesAsync(); 

There are other techniques that can be used to achieve a similar outcome, however their suitability greatly depends on how you store the columns to be sorted, if you allow multi-column sorting and if you allow different directions in your multi-column sort.

Upvotes: 1

Related Questions