-
-
Notifications
You must be signed in to change notification settings - Fork 231
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature] Extend OrderBy functionality #73
Comments
This library already supports ordering like: var orderByComplex1 = qry.OrderBy("Profile.Age, Id"); So what else do you need? |
Something like var orderByComplex = query.OrderBy("(Profile.Instagram.Cost ?? 0) + (Profile.Facebook.Cost ?? 0) == 0 ? 1 : 0").ThenBy("(Profile.Instagram.Cost ?? 0) + (Profile.Facebook.Cost ?? 0)") |
This looks like not valid Linq. Can you rewrite you question into a normal Linq query ? |
Might not be a valid Linq expression. The query I'm after is to sort those that doesn't have any cost ( Currently I do this by return an |
The solution ended up as Infrastructurepublic interface ISortableExpressionFactory<TModel>
{
bool CanResolve(string key);
ISortableExpressionAction<TModel> Resolve(string key);
}
public interface ISortableExpressionAction<TModel>
{
IOrderedQueryable<TModel> Execute(IQueryable<TModel> query, bool ascending);
} Sortingpublic static IQueryable<TModel> SortBy<TModel>(this IQueryable<TModel> query, string sortExpressions, ISortableExpressionFactory<TModel> factory) where TModel : class
{
var sortables = sortExpressions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
.Select(expression => new Sortable(expression))
.ToList();
foreach (var sortable in sortables)
{
if (factory.CanResolve(sortable.Property))
{
var sorter = factory.Resolve(sortable.Property);
query = sorter.Execute(query, !sortable.Descending);
}
else
{
query = query.SortBy(sortable); // Same is issue body
}
}
return query;
} Modelpublic class Sortable
{
internal Sortable(string expression)
{
var parts = expression.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0 || parts.Length > 2)
{
throw new ArgumentException("Expression must be of form 'TKey [ASC | DESC]'", nameof(expression));
}
Property = parts[0];
if (parts.Length == 2)
{
Descending = "DESC".Equals(parts[1], StringComparison.OrdinalIgnoreCase);
}
}
public Sortable(LambdaExpression expression, Type expressionType, bool descending = false, bool nullLast = true)
{
Expression = expression;
ExpressionType = expressionType;
Descending = descending;
NullLast = nullLast;
}
public static Sortable Create<TModel, TKey>(Expression<Func<TModel, TKey>> expression, bool descending = false, bool nullLast = true)
{
return new Sortable(expression, expression.ReturnType, descending, nullLast);
}
public LambdaExpression Expression { get; }
public Type ExpressionType { get; set; }
public string Parameter { get; set; }
public bool NullLast { get; }
public string Property { get; }
public bool Descending { get; }
} Then a can implement reusable components of type class CostSorter : ISortableExpressionAction<Profile>
{
public IOrderedQueryable<Profile> Execute(IQueryable<Profile> query, bool ascending)
{
var orderable = query
.OrderBy(Profile.FilterExpressions.OrderByCostNull());
if (ascending)
{
orderable = orderable.ThenBy(Profile.FilterExpressions.OrderByCost());
}
else
{
orderable = orderable.ThenByDescending(Profile.FilterExpressions.OrderByCost());
}
return orderable;
}
} and simply execute |
I'm glad you could make it work. |
Hi,
Haven't used this package (yet) but it seem to have a lot of functionality that I might use as my project evolves. It also lacks the only functionality I currently need :) Since the reflection calls, expression tree parsing is probably more efficient than my code I thought to create a PR with a new feature.
To the point: I use EF Core (currently in a MVC application) with an extension
OrderBy
that takes a stringProperty [ASC | DESC] | ["," ...]
(abusing BNF ;). However I need to be able to order by more complex expressions such asp => p.A.Cost + p.B.Cost + ...
etc where, in this example,Cost
might be nullable. So I also need to sort null values last, if desired.So I've created a class
Orderable
Extension method
So, is this something that is align with the project? If so I'm happy to create a PR.
Regards
The text was updated successfully, but these errors were encountered: