Marc Gravell Dynamic Linq OrderBy Extension

I found the dynamic order of Mark Gravell great:

Dynamic LINQ OrderBy on IEnumerable <T>

I put it in a class, LinqHelper . In this class, I also created two new classes, so in my code I can do this:

 var q = db.tblJobHeaders; LinqHelper.OrderByCollection OBys = new LinqHelper.OrderByCollection(); OBys.AddOrderBy("some field", true); OBys.AddOrderBy("anotherfield", false); OBys.ExecuteOrderBys(q); 

Classes for this:

 /// <summary> /// A collection of order bys /// </summary> public class OrderByCollection { private ArrayList Orderings = new ArrayList(); public OrderByCollection(){ } /// <summary> /// Add an order by to this collection /// </summary> public void AddOrderBy(string Field, bool Descending) { OrderByObj NewObj = new OrderByObj(Descending, Field); this.Orderings.Add(NewObj); } /// <summary> /// Executes the order bys /// </summary> public IOrderedQueryable<T> ExecuteOrderBys<T>(this IOrderedQueryable<T> source) { int ExecutionIndex = 0; foreach (OrderByObj O in this.Orderings) { if (ExecutionIndex == 0) { if (O.Descending) source = LinqHelper.OrderByDescending(source, O.Field); else source = LinqHelper.OrderBy(source, O.Field); } else { if (O.Descending) source = LinqHelper.ThenByDescending(source, O.Field); else source = LinqHelper.ThenBy(source, O.Field); } ExecutionIndex++; } return (IOrderedQueryable<T>)source; } } /// <summary> /// An order by object /// </summary> private class OrderByObj { public bool Descending { get; set; } public string Field { get; set; } public OrderByObj(bool IsDescending, string DatabaseField) { this.Descending = IsDescending; this.Field = DatabaseField; } } 

No matter how new I am to passing Linq vars through functions (it bothers me a bit). I am currently getting the error message:

 OBys.ExecuteOrderBys(q); 

Which gives an error:

Type arguments for the 'LinqHelper.OrderByCollection.ExecuteOrderBys (System.Linq.IOrderedQueryable)' method cannot be taken out of use. Try specifying type arguments explicitly.

I'm a little confused by this, if anyone can help, am I passing var q correctly and then returning it correctly?

+7
source share
1 answer

I am sure that type q is IQueryable<T> , not IOrderedQueryable<T> . Just changing the signature should work, because you start with OrderBy .

Then you need IOrderedQueryable<T> for ThenBy s. You can just drop it because you know for sure that you have an IOrderedQueryable<T> from the previous call to ThenBy or ThenBy .

If you do not like the idea of ​​translation, you will need some changes:

 public IOrderedQueryable<T> ExecuteOrderBys<T>(this IQueryable<T> source) { if(!this.Orderings.Any()) throw new InvalidOperationException("You need to add orderings"); IOrderedQueryable<T> ordered; if (this.Orderings[0].Descending) ordered = LinqHelper.OrderByDescending(source, this.Orderings[0].Field); else ordered = LinqHelper.OrderBy(source, this.Orderings[0].Field); foreach(var ordering in this.Orderings.Skip(1)) { if (ordering.Descending) ordered = LinqHelper.ThenByDescending(source, ordering.Field); else ordered = LinqHelper.ThenBy(source, ordering.Field); } return ordered; } 

Please note that your code will not succeed spectacularly unless you add any orders, due to the casting in the IOrderedQueryable<T> at the end. You can change the return type to IQueryable<T> (which loses the ability to "attach" more OrderBys later) or drop if there are no orders, like me.

+4
source

All Articles