696

I found an example in the VS2008 Examples for Dynamic LINQ that allows you to use a sql-like string (e.g. OrderBy("Name, Age DESC")) for ordering. Unfortunately, the method included only works on IQueryable<T>. Is there any way to get this functionality on IEnumerable<T>?

Selim Yildiz
  • 4,224
  • 6
  • 14
  • 25
John Sheehan
  • 74,152
  • 28
  • 154
  • 191
  • 2
    The best answer as of this date, in my opinion: [System.Linq.Dynamic.Core](https://github.com/StefH/System.Linq.Dynamic.Core) library. – Shahin Dohan Oct 07 '18 at 22:50

20 Answers20

926

Just stumbled into this oldie...

To do this without the dynamic LINQ library, you just need the code as below. This covers most common scenarios including nested properties.

To get it working with IEnumerable<T> you could add some wrapper methods that go via AsQueryable - but the code below is the core Expression logic needed.

public static IOrderedQueryable<T> OrderBy<T>(
    this IQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "OrderBy");
}

public static IOrderedQueryable<T> OrderByDescending<T>(
    this IQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "OrderByDescending");
}

public static IOrderedQueryable<T> ThenBy<T>(
    this IOrderedQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "ThenBy");
}

public static IOrderedQueryable<T> ThenByDescending<T>(
    this IOrderedQueryable<T> source, 
    string property)
{
    return ApplyOrder<T>(source, property, "ThenByDescending");
}

static IOrderedQueryable<T> ApplyOrder<T>(
    IQueryable<T> source, 
    string property, 
    string methodName) 
{
    string[] props = property.Split('.');
    Type type = typeof(T);
    ParameterExpression arg = Expression.Parameter(type, "x");
    Expression expr = arg;
    foreach(string prop in props) {
        // use reflection (not ComponentModel) to mirror LINQ
        PropertyInfo pi = type.GetProperty(prop);
        expr = Expression.Property(expr, pi);
        type = pi.PropertyType;
    }
    Type delegateType = typeof(Func<,>).MakeGenericType(typeof(T), type);
    LambdaExpression lambda = Expression.Lambda(delegateType, expr, arg);

    object result = typeof(Queryable).GetMethods().Single(
            method => method.Name == methodName
                    && method.IsGenericMethodDefinition
                    && method.GetGenericArguments().Length == 2
                    && method.GetParameters().Length == 2)
            .MakeGenericMethod(typeof(T), type)
            .Invoke(null, new object[] {source, lambda});
    return (IOrderedQueryable<T>)result;
}

Edit: it gets more fun if you want to mix that with dynamic - although note that dynamic only applies to LINQ-to-Objects (expression-trees for ORMs etc can't really represent dynamic queries - MemberExpression doesn't support it). But here's a way to do it with LINQ-to-Objects. Note that the choice of Hashtable is due to favorable locking semantics:

using Microsoft.CSharp.RuntimeBinder;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Dynamic;
using System.Linq;
using System.Runtime.CompilerServices;
static class Program
{
    private static class AccessorCache
    {
        private static readonly Hashtable accessors = new Hashtable();

        private static readonly Hashtable callSites = new Hashtable();

        private static CallSite<Func<CallSite, object, object>> GetCallSiteLocked(
            string name) 
        {
            var callSite = (CallSite<Func<CallSite, object, object>>)callSites[name];
            if(callSite == null)
            {
                callSites[name] = callSite = CallSite<Func<CallSite, object, object>>
                    .Create(Binder.GetMember(
                                CSharpBinderFlags.None, 
                                name, 
                                typeof(AccessorCache),
                                new CSharpArgumentInfo[] { 
                                    CSharpArgumentInfo.Create(
                                        CSharpArgumentInfoFlags.None, 
                                        null) 
                                }));
            }
            return callSite;
        }

        internal static Func<dynamic,object> GetAccessor(string name)
        {
            Func<dynamic, object> accessor = (Func<dynamic, object>)accessors[name];
            if (accessor == null)
            {
                lock (accessors )
                {
                    accessor = (Func<dynamic, object>)accessors[name];
                    if (accessor == null)
                    {
                        if(name.IndexOf('.') >= 0) {
                            string[] props = name.Split('.');
                            CallSite<Func<CallSite, object, object>>[] arr 
                                = Array.ConvertAll(props, GetCallSiteLocked);
                            accessor = target =>
                            {
                                object val = (object)target;
                                for (int i = 0; i < arr.Length; i++)
                                {
                                    var cs = arr[i];
                                    val = cs.Target(cs, val);
                                }
                                return val;
                            };
                        } else {
                            var callSite = GetCallSiteLocked(name);
                            accessor = target =>
                            {
                                return callSite.Target(callSite, (object)target);
                            };
                        }
                        accessors[name] = accessor;
                    }
                }
            }
            return accessor;
        }
    }

    public static IOrderedEnumerable<dynamic> OrderBy(
        this IEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.OrderBy<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> OrderByDescending(
        this IEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.OrderByDescending<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> ThenBy(
        this IOrderedEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.ThenBy<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    public static IOrderedEnumerable<dynamic> ThenByDescending(
        this IOrderedEnumerable<dynamic> source, 
        string property)
    {
        return Enumerable.ThenByDescending<dynamic, object>(
            source, 
            AccessorCache.GetAccessor(property), 
            Comparer<object>.Default);
    }

    static void Main()
    {
        dynamic a = new ExpandoObject(), 
                b = new ExpandoObject(), 
                c = new ExpandoObject();
        a.X = "abc";
        b.X = "ghi";
        c.X = "def";
        dynamic[] data = new[] { 
            new { Y = a },
            new { Y = b }, 
            new { Y = c } 
        };

        var ordered = data.OrderByDescending("Y.X").ToArray();
        foreach (var obj in ordered)
        {
            Console.WriteLine(obj.Y.X);
        }
    }
}
Dima
  • 1,589
  • 12
  • 30
Marc Gravell
  • 927,783
  • 236
  • 2,422
  • 2,784
  • 114
    Best damn piece of code I have seen :) Just solved a million problems in my project :) – sajidnizami Nov 20 '08 at 09:37
  • Marc, Do you have the similar extension for LIKE Condition? – Prasad Nov 02 '09 at 03:30
  • @Prasad - `LIKE` is a bit different, but which back end? For LINQ-to-SQL, there is `SqlMethods.Like`: http://msdn.microsoft.com/en-us/library/system.data.linq.sqlclient.sqlmethods.like.aspx; can you add more info what you are looking for? – Marc Gravell Nov 02 '09 at 05:20
  • I am using SQL as backend, i need to do a search operation with dynamic parameter names as like in your OrderBy extension. – Prasad Nov 02 '09 at 05:55
  • Well, you can certainly use `SqlMethods.Like` in a custom expression; it really isn't clear where it breaks down... can you clarify? Perhaps ask as a question? – Marc Gravell Nov 02 '09 at 06:16
  • Thanks Mark, I did in http://stackoverflow.com/questions/1654745/dynamic-linq-like yesterday. Its better if i have a sample on it – Prasad Nov 02 '09 at 06:30
  • 2
    Sounds like lots of folks had success with this code- I can't for the life of me figure out how to apply it! These are extension methods, right? How do I use them?? – Dave Swersky Jan 22 '10 at 18:22
  • 4
    @Dave - you need to start with `IQueryable`, so if you have something like `List` (which is `IEnumerable`) you may need to use `AsQueryable()` - for example `var sorted = someList.AsQueryable().OrderBy("Foo.Bar");` – Marc Gravell Jan 22 '10 at 19:26
  • 7
    Have you seen this... it might help some people... http://stackoverflow.com/questions/557819/strongly-typed-dynamic-linq-sorting/2794039#2794039 its a more strongly typed solution. – anthonyv May 08 '10 at 12:30
  • 2
    Great code ! Do you know any way to add support to the "Count()" extension method ? Calling an extension method is quiet a pain, and I have troubles building an expression with those. I'm trying to add the 'Count()' support for IQueryable which is coded as extension in the 'Queryable' type. – Mose May 17 '10 at 12:24
  • 2
    @ile - `var ordered = someData.OrderBy("Name");` - or for `IEnumerable` data, `var ordered = someData.AsQueryable().OrderBy("Name");` – Marc Gravell Jun 03 '10 at 10:01
  • 1
    This be done already with *AsQueryAble().OrderBy().ThenBy()*. There must be something I'm missing. **Edit** I just noticed the above methods are returning *IOrderedQueryable* and the methods I listed are returning *IOrderedEnumerable*. – Chuck Conway Oct 18 '10 at 21:49
  • if use switch which will be faster. reflection vs switch – Nario Apr 29 '11 at 08:41
  • @Nario - context? switch on *what*, vs *what* reflection? Oh, you mean building up with `.OrderBy(x => x.Something)` (times 10 or whatever) - the `switch`, most likely – Marc Gravell Apr 29 '11 at 09:36
  • switch(propertyname) { case "property1": result=datacontex.orderby(x=>x.property1) break; case "property2": result=datacontex.orderby(x=>x.property2) break; } – Nario Apr 29 '11 at 10:18
  • Thanks for this! One improvement I have found is, instead of the Reflection GetMethod()..Invoke() statement, you can build the result direcly in linq: var expression = Expression.Call(typeof(Queryable), methodName, new[] { source.ElementType, expr.Type }, source.Expression, lambda); var result = source.Provider.CreateQuery(expression); – automagic Jul 13 '11 at 21:14
  • Is it possible to use this approach with an object implementing IDynamicMetaObjectProvider? I'm having issues described in this post: http://stackoverflow.com/questions/11206631/dynamic-sorting-with-a-serializabledynamicobject – BonyT Jun 26 '12 at 11:50
  • @BonyT no, but I've added a "dynamic" approach to your question – Marc Gravell Jun 26 '12 at 12:20
  • @MarcGravell: I post a question in this url : http://stackoverflow.com/questions/12495873/dynamic-sort-in-linq/12495964 . and the problem is when I use your extension methods the result does not sort. what is the problem? – Arian Sep 22 '12 at 12:20
  • Thanks a lot for this code. Same question as Mose: Do you know any way to add support to the "Count()" extension method? – Julien Oct 05 '12 at 14:42
  • Is there a way I can apply a sort by a subcollection? – amhed Oct 14 '12 at 13:31
  • @ahmed depends... What does that *mean*? – Marc Gravell Oct 14 '12 at 19:25
  • 2
    If anyone is interested, I got it to work with `IEnumerable` simply substituting `lambda` with `lambda.Compile()` in the penultimate line, barring the obvious substitutions `IQueryable` > `IEnumerable` and `IOrderedQueryable` with `IOrderedEnumerable`. No wrappers involved – Piddu May 22 '13 at 07:11
  • Wow, this is ridiculous - a couple of lines of code inflated to forty just to avoid using System.Linq.Dynamic? Is there some kind of advantage to not using it? **Take a look at @Alaa Osta's answer** below (the actual solution to the original question). – MGOwen Jul 13 '13 at 01:11
  • 29
    @MGOwen you seem to misunderstand the nature of code. The 40 lines is the same no matter whether it is 40 lines that you put somewhere in your project, or if those lines come (pre-compiled, or as source) in an external library. It would have been *pretty amazing* if I had linked, in Oct '08 to a library on nuget that has existed since Dec '11 (not least because nuget didn't exist then either), but the fundamental "what it is doing" is the same. Also, you use the phrase "actual solution" as though there is some well-defined agreed single route to every coding question: there is not. – Marc Gravell Jul 13 '13 at 08:15
  • 6
    @MGOwen btw, the external lib is 2296 lines of code (not including AssemblyInfo.cs); which kinda makes the 40 lines here look pretty reasonable – Marc Gravell Jul 13 '13 at 08:18
  • @MarcGravell Ahhh OK, Sorry, didn't notice this answer was so old. I was just pretty confused, as 99% of people who find this question will be. My comment wasn't directed at you, but at them: the hundreds of people finding this question who need the best answer currently available. WRT lines of code, I think most programmers will prefer to use an established library to solve the problem, and if I understand linking correctly, only the code used will be included anyway, right? – MGOwen Jul 15 '13 at 02:03
  • @MGOwen .net doesn't use a linker (except on some AOT frameworks). All the IL will be included, but only the methods that get used will be JIT-ed – Marc Gravell Jul 15 '13 at 06:38
  • Nice, just don't rename any of the properties. – Adam Houldsworth Oct 01 '13 at 10:15
  • @MarcGravell does this sort before or after the sql is run? I also use paging so that I'll only retrieve a few records at the time, but to get the correct records the sorting must be done in the sql statement, not in memory. – Zaphod Jan 13 '14 at 14:20
  • @Zaphod as long as the input is a suitable `IQueryable`, it is composed into the query without executing anything or doing anything in-memory – Marc Gravell Jan 13 '14 at 15:38
  • Very nice code, it helped me a lot with ordering by column name stored in string. However it doesn't work all that well with interfaces. I mean if you have a IQueryable of an interface class and try to order by a column that isn't part of the interface you'll get an error. Thankfully it's easy enough to fix. Replacing all instances of typeof(T) with source.ElementType will allow ordering by any column of the actual class that is handled within the query. – jahu Jan 30 '14 at 16:30
  • @MarcGravell, In the first snippet you don't need to compute yourself the delegateType of the LambdaExpression. If you don't pass it as first argument it is computed automatically by Expression.Lambda. – Francesco Abbruzzese Dec 29 '16 at 19:17
  • 1
    Very nice... In my extremely basic test this executes in 29 ms vs `System.Linq.Dynamic`'s 148 ms. – Shawn Beachy Jul 27 '18 at 17:27
  • I can't understand even single line from this code, but it works! – Jakub Szułakiewicz May 28 '19 at 07:32
  • I'm using the first part of code and it works very cool. But after changing the project to .net Core 3.0 the nullable-warnings are driving me crazy. Could you please update the code? – Henning Oct 14 '19 at 08:35
  • @Henning (places tongue in cheek) - sure! `#nullable disable` – Marc Gravell Oct 14 '19 at 09:09
  • @MarcGravell Hey master, do I need to escape the input to prevent injections? – Nicholas Dec 02 '19 at 15:55
  • 1
    @Nicholas no, the expression-tree parser/SQL generator layer deals with that, as parameters – Marc Gravell Dec 02 '19 at 16:18
248

Too easy without any complication:

  1. Add using System.Linq.Dynamic; at the top.
  2. Use vehicles = vehicles.AsQueryable().OrderBy("Make ASC, Year DESC").ToList();
poke
  • 307,619
  • 61
  • 472
  • 533
Alaa Osta
  • 3,589
  • 6
  • 21
  • 27
55

Just stumbled across this question.

Using Marc's ApplyOrder implementation from above, I slapped together an Extension method that handles SQL-like strings like:

list.OrderBy("MyProperty DESC, MyOtherProperty ASC");

Details can be found here: http://aonnull.blogspot.com/2010/08/dynamic-sql-like-linq-orderby-extension.html

Adam Anderson
  • 707
  • 7
  • 7
  • 1
    Great stuff, just add a modification as follows to make the property name case insensitive: PropertyInfo pi = type.GetProperty(prop,BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase); – Mrinal Kamboj May 29 '16 at 07:47
46

I guess it would work to use reflection to get whatever property you want to sort on:

IEnumerable<T> myEnumerables
var query=from enumerable in myenumerables
          where some criteria
          orderby GetPropertyValue(enumerable,"SomeProperty")
          select enumerable

private static object GetPropertyValue(object obj, string property)
{
    System.Reflection.PropertyInfo propertyInfo=obj.GetType().GetProperty(property);
    return propertyInfo.GetValue(obj, null);
}

Note that using reflection is considerably slower than accessing the property directly, so the performance would have to be investigated.

Kjetil Watnedal
  • 5,671
  • 3
  • 24
  • 22
20

Just building on what others have said. I found that the following works quite well.

public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> input, string queryString)
{
    if (string.IsNullOrEmpty(queryString))
        return input;

    int i = 0;
    foreach (string propname in queryString.Split(','))
    {
        var subContent = propname.Split('|');
        if (Convert.ToInt32(subContent[1].Trim()) == 0)
        {
            if (i == 0)
                input = input.OrderBy(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenBy(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        else
        {
            if (i == 0)
                input = input.OrderByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
            else
                input = ((IOrderedEnumerable<T>)input).ThenByDescending(x => GetPropertyValue(x, subContent[0].Trim()));
        }
        i++;
    }

    return input;
}
poke
  • 307,619
  • 61
  • 472
  • 533
vdhant
  • 2,148
  • 3
  • 22
  • 28
12

I was trying to do this but having problems with Kjetil Watnedal's solution because I don't use the inline linq syntax - I prefer method-style syntax. My specific problem was in trying to do dynamic sorting using a custom IComparer.

My solution ended up like this:

Given an IQueryable query like so:

List<DATA__Security__Team> teams = TeamManager.GetTeams();
var query = teams.Where(team => team.ID < 10).AsQueryable();

And given a run-time sort field argument:

string SortField; // Set at run-time to "Name"

The dynamic OrderBy looks like so:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField));

And that's using a little helper method called GetReflectedPropertyValue():

public static string GetReflectedPropertyValue(this object subject, string field)
{
    object reflectedValue = subject.GetType().GetProperty(field).GetValue(subject, null);
    return reflectedValue != null ? reflectedValue.ToString() : "";
}

One last thing - I mentioned that I wanted the OrderBy to use custom IComparer - because I wanted to do Natural sorting.

To do that, I just alter the OrderBy to:

query = query.OrderBy(item => item.GetReflectedPropertyValue(SortField), new NaturalSortComparer<string>());

See this post for the code for NaturalSortComparer().

Cœur
  • 32,421
  • 21
  • 173
  • 232
James McCormack
  • 8,920
  • 3
  • 45
  • 55
12

I've stumble this question looking for Linq multiple orderby clauses and maybe this was what the author was looking for

Here's how to do that:

var query = pets.OrderBy(pet => pet.Name).ThenByDescending(pet => pet.Age);    
Shimmy Weitzhandler
  • 92,920
  • 119
  • 388
  • 596
InfoStatus
  • 6,228
  • 9
  • 35
  • 48
  • 5
    +1 canceled the down-vote due to lack of explanation. I also think the author might have been interested in multiple order-bys. Even if dynamic *was* the key word, no reason to down-vote. – Jason Kleban May 25 '10 at 18:51
8

Use dynamic linq

just add using System.Linq.Dynamic;

And use it like this to order all your columns:

string sortTypeStr = "ASC"; // or DESC
string SortColumnName = "Age"; // Your column name
query = query.OrderBy($"{SortColumnName} {sortTypeStr}");
Masoud Darvishian
  • 3,080
  • 4
  • 27
  • 37
5

After a lot of searching this worked for me:

public static IEnumerable<TEntity> OrderBy<TEntity>(this IEnumerable<TEntity> source, 
                                                    string orderByProperty, bool desc)
{
    string command = desc ? "OrderByDescending" : "OrderBy";
    var type = typeof(TEntity);
    var property = type.GetProperty(orderByProperty);
    var parameter = Expression.Parameter(type, "p");
    var propertyAccess = Expression.MakeMemberAccess(parameter, property);
    var orderByExpression = Expression.Lambda(propertyAccess, parameter);
    var resultExpression = Expression.Call(typeof(Queryable), command, 
                                           new[] { type, property.PropertyType },
                                           source.AsQueryable().Expression, 
                                           Expression.Quote(orderByExpression));
    return source.AsQueryable().Provider.CreateQuery<TEntity>(resultExpression);
}
nawfal
  • 62,042
  • 48
  • 302
  • 339
Sanchitos
  • 7,552
  • 4
  • 44
  • 49
4

Thanks to Maarten (Query a collection using PropertyInfo object in LINQ) I got this solution:

myList.OrderByDescending(x => myPropertyInfo.GetValue(x, null)).ToList();

In my case I was working on a "ColumnHeaderMouseClick" (WindowsForm) so just found the specific Column pressed and its correspondent PropertyInfo:

foreach (PropertyInfo column in (new Process()).GetType().GetProperties())
{
    if (column.Name == dgvProcessList.Columns[e.ColumnIndex].Name)
    {}
}

OR

PropertyInfo column = (new Process()).GetType().GetProperties().Where(x => x.Name == dgvProcessList.Columns[e.ColumnIndex].Name).First();

(be sure to have your column Names matching the object Properties)

Cheers

Community
  • 1
  • 1
joaopintocruz
  • 261
  • 3
  • 11
4

Here's something else I found interesting. If your source is a DataTable, you can use dynamic sorting without using Dynamic Linq

DataTable orders = dataSet.Tables["SalesOrderHeader"];
EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         orderby order.Field<DateTime>("OrderDate")
                                         select order;
DataView view = query.AsDataView();
bindingSource1.DataSource = view;

reference: http://msdn.microsoft.com/en-us/library/bb669083.aspx (Using DataSetExtensions)

Here is one more way to do it by converting it to a DataView:

DataTable contacts = dataSet.Tables["Contact"];    
DataView view = contacts.AsDataView();    
view.Sort = "LastName desc, FirstName asc";    
bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
Sameer Alibhai
  • 2,836
  • 4
  • 32
  • 35
4

You can convert the IEnumerable to IQueryable.

items = items.AsQueryable().OrderBy("Name ASC");
Richard YS
  • 1,232
  • 11
  • 10
4

You could add it:

public static IEnumerable<T> OrderBy( this IEnumerable<T> input, string queryString) {
    //parse the string into property names
    //Use reflection to get and sort by properties
    //something like

    foreach( string propname in queryString.Split(','))
        input.OrderBy( x => GetPropertyValue( x, propname ) );

    // I used Kjetil Watnedal's reflection example
}

The GetPropertyValue function is from Kjetil Watnedal's answer

The issue would be why? Any such sort would throw exceptions at run-time, rather than compile time (like D2VIANT's answer).

If you're dealing with Linq to Sql and the orderby is an expression tree it will be converted into SQL for execution anyway.

Community
  • 1
  • 1
Keith
  • 133,927
  • 68
  • 273
  • 391
4

First Install Dynamic Tools --> NuGet Package Manager --> Package Manager Console

install-package System.Linq.Dynamic

Add Namespace using System.Linq.Dynamic;

Now you can use OrderBy("Name, Age DESC")

Aminur Rahman
  • 315
  • 2
  • 10
4

You can use this:

        public List<Book> Books(string orderField, bool desc, int skip, int take)
{
    var propertyInfo = typeof(Book).GetProperty(orderField);

    return _context.Books
        .Where(...)
        .OrderBy(p => !desc ? propertyInfo.GetValue(p, null) : 0)
        .ThenByDescending(p => desc ? propertyInfo.GetValue(p, null) : 0)
        .Skip(skip)
        .Take(take)
        .ToList();
}
  • A couple of years later and I stumble upon this; this worked for me, like a dream. I have dynamic sorting on 1 to 3 properties, and this works like a dream. Easy to implement and hassle free. – Bazïnga Mar 22 '20 at 06:44
  • Love this answer, but how can I make this work if I need to sort by a property of a child class? – RoLYroLLs Jul 20 '20 at 21:17
3

This answer is a response to the comments that need an example for the solution provided by @John Sheehan - Runscope

Please provide an example for the rest of us.

in DAL (Data Access Layer),

The IEnumerable version:

public  IEnumerable<Order> GetOrders()
{
    // i use Dapper to return IEnumerable<T> using Query<T>
    //.. do stuff

    return orders  // IEnumerable<Order>
}

The IQueryable version

public IQueryable<Order> GetOrdersAsQuerable()
{
    IEnumerable<Order> qry= GetOrders();

    // use the built-in extension method  AsQueryable in  System.Linq namespace
    return qry.AsQueryable();            
}

Now you can use the IQueryable version to bind, for example GridView in Asp.net and benefit for sorting (you can't sort using IEnumerable version)

I used Dapper as ORM and build IQueryable version and utilized sorting in GridView in asp.net so easy.

Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
M.Hassan
  • 7,947
  • 4
  • 45
  • 67
3

An alternate solution uses the following class/interface. It's not truly dynamic, but it works.

public interface IID
{
    int ID
    {
        get; set;
    }
}

public static class Utils
{
    public static int GetID<T>(ObjectQuery<T> items) where T:EntityObject, IID
    {
        if (items.Count() == 0) return 1;
        return items.OrderByDescending(u => u.ID).FirstOrDefault().ID + 1;
    }
}
Mike Christiansen
  • 1,010
  • 1
  • 12
  • 28
0

Convert List to IEnumerable or Iquerable, add using System.LINQ.Dynamic namespace, then u can mention the property names in comma seperated string to OrderBy Method which comes by default from System.LINQ.Dynamic.

user145610
  • 2,601
  • 4
  • 36
  • 67
0

you can do it like this for multiple order by

IOrderedEnumerable<JToken> sort;

if (query.OrderBys[0].IsDESC)
{
    sort = jarry.OrderByDescending(r => (string)r[query.OrderBys[0].Key]);
}
else
{
    sort = jarry.OrderBy(r =>
        (string) r[query.OrderBys[0].Key]); 
}

foreach (var item in query.OrderBys.Skip(1))
{
    if (item.IsDESC)
    {
        sort = sort.ThenByDescending(r => (string)r[item.Key]);
    }
    else
    {
        sort = sort.ThenBy(r => (string)r[item.Key]);
    }
}
Uwe Keim
  • 36,867
  • 50
  • 163
  • 268
-4
var result1 = lst.OrderBy(a=>a.Name);// for ascending order. 
 var result1 = lst.OrderByDescending(a=>a.Name);// for desc order. 
Arindam
  • 176
  • 1
  • 5