entity framework - How to check if IQueryable<T> has OrderBy applied before before attempting Skip() and Take() -


i trying build extension method paginated query. in order avoid exception: system.notsupportedexception unhandled user code message=the method 'skip' supported sorted input in linq entities. method 'orderby' must called before method 'skip'.

i'd check if orderby applied , if not return query... this:

public static iqueryable<t> paginate<t>(this iqueryable<t> query, int page, int pagesize = 50, int total = -1) {     // check if orderby applied      // not work!!!     //try     //{     //    var orderedqueryable = query iorderedqueryable<t>;     //}     //catch (exception)     //{     //    // if cast throws orderby not applied <-- not work!!!     //    return query;     //}     page = (page < 1) ? 1 : page;     var limit = (pagesize <= 0 || (total >= 0 && pagesize > total)) ? 50 : pagesize;     var skip = (page - 1)*limit;      return query.skip(skip).take(limit); } 

to make things more interesting, using mycrosoft's dynamic expression api (aka dynamic linq) calling code looks like

return query          .orderby("customer.lastname desc, customer.firstname")          .paginate(1,25, 2345)          .toarray(); 

or can invoke using typed expressions this

return query         .orderbydescending(c=>c.lastname)         .thenby(c=>c.firstname)         .paginate(1,25,2345)         .toarray(); 

is type of checking possible? tired using iorderablequeryable<t> in method signature dynamic linq not return iorderablequeryable when use orderby(string expression) extension not apply...

update

using suggestion (pointed out @gertarnold) workable solution inspect expression tree. however, instead of making use of entire expressionvisitor simplified solution requiring paginate method must called after orderby or orderbydescending. allowed me check current node in expression tree instead of searching whole tree. did:

// snip....class level  private static readonly string[] paginationprerequisitemehods = new[] { "orderby", "orderbydescending" };  // snip paginate method public static iqueryable<t> paginate<t>(this iqueryable<t> query, int page, int pagesize = 50, int total = -1)     {         // require either orderby or orderbydescending applied before calling paginate....         if (query.expression.nodetype != expressiontype.call)         {             //todo: logging -> "you have apply orderby() or orderbydescending() before calling paginate()"             return query;         }         var methodname = ((methodcallexpression) query.expression).method.name;         if (!array.exists(paginationprerequisitemehods, s => s.equals(methodname, stringcomparison.invariantculture)))         {             //todo: logging -> "you have apply orderby() or orderbydescending() before calling paginate()"             return query;         }          page = (page < 1) ? 1 : page;         var limit = (pagesize <= 0 || (total >= 0 && pagesize > total)) ? 50 : pagesize;         var skip = (page - 1)*limit;          return query.skip(skip).take(limit);     } 

you can check expression itself, described here, or check compile-time type, described here. think former should work you, because dynamic linq adds orderby (or orderbydescending) expression.


Comments

Popular posts from this blog

jquery - Invalid Assignment Left-Hand Side -

java - Play! framework 2.0: How to display multiple image? -

gmail - Is there any documentation for read-only access to the Google Contacts API? -