0

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?

Timus
  • 10,974
  • 5
  • 14
  • 28
Manzini
  • 13
  • 2

3 Answers3

2

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();
NetMage
  • 26,163
  • 3
  • 34
  • 55
0

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

urlreader
  • 6,319
  • 7
  • 57
  • 91
  • `context.table` implies LINQ to database, and I am not sure that would translate well to SQL, not to mention being a type error (`&&` expects a `boolean` on both sides) - you need to use `?:`. – NetMage Dec 29 '20 at 01:06
  • I made the changes. You get the idea – urlreader Dec 29 '20 at 01:21
0

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;
    }
}
Svyatoslav Danyliv
  • 21,911
  • 3
  • 16
  • 32