1

I coded two LINQ statements with different orderBy. Is there a way that I could change the orderBy without having to code twice like this:

        if (param == "s")
        {
            var result = await db.PhraseCategories
                                 .OrderBy(p => p.SortOrder)
                                 .Select(p => new
                                 {
                                     Id = p.PhraseCategoryShortId,
                                     Name = p.Name
                                 })
                                 .AsNoTracking()
                                 .ToListAsync();
            return Ok(result);
        } 

        if (param == "n")
        {
            var result = await db.PhraseCategories
                 .OrderBy(p => p.Name)
                 .Select(p => new
                 {
                     Id = p.PhraseCategoryShortId,
                     Name = p.Name
                 })
                 .AsNoTracking()
                 .ToListAsync();
            return Ok(result);
        }
Alan2
  • 23,493
  • 79
  • 256
  • 450

2 Answers2

4
var result = await db.PhraseCategories
    .OrderBy(p => param == "s" ? p.SortOrder : p.Name)
    .Select(p => new
    {
        Id = p.PhraseCategoryShortId,
        Name = p.Name
    })
    .AsNoTracking()
    .ToListAsync();

return Ok(result);
mountain traveller
  • 7,591
  • 33
  • 38
  • You could of course code more precisely for `param == "n"` rather than just use the 'else' half of `? :`, if you wish. Your original code sample didn't indicate what would happen if `param` matched neither `"n"` nor `"s"` – mountain traveller Oct 15 '16 at 11:31
  • good option, for 2 , but not for more ... back to defining the predicate i'm afraid – Noctis Oct 15 '16 at 11:32
  • @Noctis perfectly possible for more than 2, with nested `? :` - but not very readable. For more than 2, I would probably, like you, go with pulling the sorting logic out into a predicate beforehand. – mountain traveller Oct 15 '16 at 11:35
  • if you start nesting `? :` you're in almost the same place where you started (bit better, but still not easy to read). Might be what Alan needs though – Noctis Oct 15 '16 at 11:37
4

Other option can be to work on query like:

IQueryable<PhraseCategory> query = db.PhraseCategories;

// Order as needed
if(param == "s")
    query = query.OrderBy(m => m.SortOrder);
else if(param == "n")
    query = query.OrderBy(m => m.Name);

var result = await query
    .Select(p => new
    {
     Id = p.PhraseCategoryShortId,
     Name = p.Name
    })
    .AsNoTracking()
    .ToListAsync();     
return Ok(result);

Additionally, if you can get param in the form of property name to order according to, then you can write extension method to dynamically order according to property name as shown in this answer.

Community
  • 1
  • 1
Adil Mammadov
  • 8,476
  • 4
  • 31
  • 59
  • 1
    I like this too. We use this approach internally to _progressively_ add further sorts to a query, according to whether the user has selected extra sub-sorts. IE continue to apply extra `.ThenBy()` clauses to a query, before execution, for each extra sub-sort a user has selected. – mountain traveller Oct 15 '16 at 12:00