Reputation: 4802
I have a model class
public class MyModel
{
public long Id { get; set; }
public string Name { get; set; }
}
I am currently returning an ordered list (by name) of MyModel
from database :
return await Db.MyModel
.AsNoTracking()
.OrderBy(x => x.Name)
However, one of the values in database is "N/A" and I am looking to order by some selector whilst leaving "N/A" last, so basically:
return await Db.MyModel
.AsNoTracking()
.OrderBy(x => x.Name == "N/A)
.ThenBy(x => x.Name)
I created an IQueryable
extension, but I am getting an error on the Expression.Call(...)
InvalidOperationException: No generic method 'OrderBy' on type 'System.Linq.Queryable' is compatible with the supplied type arguments and arguments. No type arguments should be provided if the method is non-generic.
public static IQueryable<TSource> OrderNALast<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, string>> selector)
{
var expression = source.Expression;
var parameter = Expression.Parameter(typeof(TSource), "x");
var left = (MemberExpression)selector.Body;
var right = Expression.Constant("N/A");
var predicateBody = Expression.Equal(left, right);
var lambda = Expression.Lambda<Func<TSource, bool>>(predicateBody, parameter);
expression = Expression.Call(
typeof(Queryable),
"OrderBy",
new[] { source.ElementType, left.Type },
expression,
lambda);
var appendedQuery = (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(expression);
return appendedQuery.ThenBy(selector);
}
Upvotes: 1
Views: 283
Reputation: 3053
Oh, I think I see the problem.
In Expression.Call, the third argument requires the static method's generic type arguments to call.
Queryable.OrderBy()
has two overloads:
public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector, System.Collections.Generic.IComparer<TKey> comparer);
and
public static System.Linq.IOrderedQueryable<TSource> OrderBy<TSource,TKey> (this System.Linq.IQueryable<TSource> source, System.Linq.Expressions.Expression<Func<TSource,TKey>> keySelector);
But instead of giving
TSource
and bool
as arguments, you are giving it
TSource
and string
as arguments.
So it should be:
expression = Expression.Call(
typeof(Queryable),
"OrderBy",
new[] { typeof(TSource), typeof(bool) },
expression,
lambda);
(Or you can also use source.ElementType for the first type.)
Upvotes: 1