Manzini
Manzini

Reputation: 13

Different OrderBy based on different filters

I have as scenario like this:

One supposed query

var list = (from p in context.table select p.field)

and different "orderby" based on the client choice .

The simple way to do it would look like this:

if (filter.Equals("filter1"))
{
    var list = (from p in context.table select p.field).OrderBy(w=> w.filter1);
}
else if (filter.Equals("filter2"))
{
    var list = (from p in context.table select p.field).OrderBy(w=> w.filter2);
}

But since there is a lot of filters, it feels like it is an ugly practice to repeat the same query a lot of times just to change the OrderBy condition, does someone know what would be the best/cleaner approach?

Upvotes: 0

Views: 68

Answers (3)

Svyatoslav Danyliv
Svyatoslav Danyliv

Reputation: 27282

I would suggest another approach with extension method.

var q = (from p in context.table select p)
    .OrderByIf(filter.Equals("filter1"), w => w.filter1)
    .OrderByIf(filter.Equals("filter2"), w => w.filter2)
    .OrderByIf(filter.Equals("filter2"), w => w.filter2)
    ...
    ;
var list = q.Select(x => x.field).ToList();
public static class QueryableExtensions
{
    public static IQueryable<T> OrderByIf<T, TKey>(this IQueryable<T> query, 
       bool cond, Expression<Func<T, TKey>> prop)
    {
        if (cond)
        {
            query = query.OrderBy(prop);
        }

        return query;
    }
}

Upvotes: 0

urlreader
urlreader

Reputation: 6605

first of all, I think, what you did is not bad at all. pretty straightforward. but if you really want to make it 'better' (actually not sure it is better, but at least it is a way):

var q = (from p in context.table select p)
    .OrderBy(w => filter.Equals("filter1") ? w.filter1 : "")
    .OrderBy(w => filter.Equals("filter2") ? w.filter2 : "")
    .OrderBy(w => filter.Equals("filter3") ? w.filter3 : "")
    ...
    ;
var list = q.Select(x => x.field).ToList();

something like this

Upvotes: 0

NetMage
NetMage

Reputation: 26907

If your filters vary in type, you can use a switch-case to select a filter:

var query = from p in context.table select p;
switch (filter) {
    case "filter1":
        query = query.OrderBy(r => r.filter1);
        break;
    case "filter2":
        query = query.OrderBy(r => r.filter2);
        break;
}
var list = query.Select(r => r.field).ToList();

If your filters are uniform in type, you can use a Dictionary to lookup the filter lambda Expression:

var q2 = from p in context.table select p;
var filterMap = new Dictionary<string, Expression<Func<Table, int>>> {
    { "filter1", (Table r) => r.filter1 },
    { "filter2", (Table r) => r.filter2 },
};

if (filterMap.TryGetValue(filter, out var orderFne))
    q2 = q2.OrderBy(orderFne);
var l2 = query.Select(r => r.field).ToList();

Upvotes: 2

Related Questions