Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I cannot explain why using an <code>Int32</code> does not work but using a <code>string</code>. Aren't both EDM "primitive" types and do not both implement <code>IComparable</code>? I don't understand the different behaviour.</p> <p>Anyway, it seems to be necessary to pass in every expression in the collection with the concrete type it should be sorted by to avoid the failing type cast. In other words not an <code>IComparable</code>, but instead an <code>int</code>, a <code>string</code>, a <code>DateTime</code>, etc.</p> <p>I had success to achieve this along the lines of the idea in this answer: <a href="https://stackoverflow.com/questions/225481/how-to-check-for-the-presence-of-an-orderby-in-a-objectqueryt-expression-tree/225749#225749">How to check for the presence of an OrderBy in a ObjectQuery&lt;T&gt; expression tree</a></p> <p>Define an interface which does <em>not</em> depend on the type to sort by but only the entity type. (The example below is generalized to arbitrary entities. If you only want that for <code>User</code> remove the generic parameter and replace <code>TEntity</code> in the queryables by <code>User</code>.)</p> <pre><code>public interface IOrderByExpression&lt;TEntity&gt; where TEntity : class { IOrderedQueryable&lt;TEntity&gt; ApplyOrderBy(IQueryable&lt;TEntity&gt; query); IOrderedQueryable&lt;TEntity&gt; ApplyThenBy(IOrderedQueryable&lt;TEntity&gt; query); } </code></pre> <p>Define an implementation of that interface which now takes the type to sort by as a second generic parameter:</p> <pre><code>public class OrderByExpression&lt;TEntity, TOrderBy&gt; : IOrderByExpression&lt;TEntity&gt; where TEntity : class { private Expression&lt;Func&lt;TEntity, TOrderBy&gt;&gt; _expression; private bool _descending; public OrderByExpression(Expression&lt;Func&lt;TEntity, TOrderBy&gt;&gt; expression, bool descending = false) { _expression = expression; _descending = descending; } public IOrderedQueryable&lt;TEntity&gt; ApplyOrderBy( IQueryable&lt;TEntity&gt; query) { if (_descending) return query.OrderByDescending(_expression); else return query.OrderBy(_expression); } public IOrderedQueryable&lt;TEntity&gt; ApplyThenBy( IOrderedQueryable&lt;TEntity&gt; query) { if (_descending) return query.ThenByDescending(_expression); else return query.ThenBy(_expression); } } </code></pre> <p>Then <code>ApplyOrderBy</code> would look like this:</p> <pre><code>public IQueryable&lt;TEntity&gt; ApplyOrderBy&lt;TEntity&gt;(IQueryable&lt;TEntity&gt; query, params IOrderByExpression&lt;TEntity&gt;[] orderByExpressions) where TEntity : class { if (orderByExpressions == null) return query; IOrderedQueryable&lt;TEntity&gt; output = null; foreach (var orderByExpression in orderByExpressions) { if (output == null) output = orderByExpression.ApplyOrderBy(query); else output = orderByExpression.ApplyThenBy(output); } return output ?? query; } </code></pre> <p>And it can be used the following way:</p> <pre><code>var query = context.Users ... ; var queryWithOrderBy = ApplyOrderBy(query, new OrderByExpression&lt;User, string&gt;(u =&gt; u.UserName), // a string, asc new OrderByExpression&lt;User, int&gt;(u =&gt; u.UserId, true)); // an int, desc var result = queryWithOrderBy.ToList(); // didn't throw an exception for me </code></pre> <p>The need to specify the generic type parameters explicitely in the <code>OrderByExpression</code> instances is not nice but I couldn't find a way so that the compiler infers the types. (I was hoping it would, because the compiler infers the <code>User</code> as <code>TEntity</code> from <code>query</code> for the <code>ApplyOrderBy</code> method, then I expected that it knows the <code>TEntity</code> of <code>OrderByExpression</code> (equals <code>User</code> as well). So the lambda parameter <code>u</code> should be known as a <code>User</code> and then the compiler could derive the type from <code>UserName</code> as <code>string</code> and from <code>UserId</code> as <code>int</code>. But this theory is apparently wrong. The compiler complains and wants to have the generic types explicitly.)</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload