Sign up ×
Stack Overflow is a community of 4.7 million programmers, just like you, helping each other. Join them; it only takes a minute:

I have the following code:

IQueryable<Guid> GetOrdered(IQueryable<Guid> ids)
{
    return from id in ids join storedId in storedIds on id equals storedId.Id
        orderby storedId.Something select id;
}

Now I want to introduce a parameter to GetOrdered() and optionally change orderby with orderby descending. Something like this:

IQueryable<Guid> GetOrdered(IQueryable<Guid> ids, bool descending)
{
    // how do I insert descending into the query below?
    return from id in ids join storedId in storedIds on id equals storedId.Id
        orderby storedId.Something select id;
}

Of course I could write two identical queries - one with orderby and another with orderby descending but that means code duplication.

Alternatively I could use a sub-statement for an unordered set and then conditionally order it like in this answer but the problem is I then need to Select() a specific column and that latter Select() will render an unordered result.

So I could try to craft a "smart" ordering condition as in this answer:

var result = from w in widgets where w.Name.Contains("xyz")
  orderby
    flag ? w.Id : 0,
    flag ? 0 : w.Id descending
  select w;

but the problem is I will often have a non-numeric column as one by which I need my set ordered.

How do I conditionally reverse the sorting order under these conditions?

share|improve this question
    
I don't understand why you cant use the "sub-statement with conditionall order" solution? – Magnus Jun 3 '13 at 11:10
    
@Magnus: That's because it will be first "ordered", then "filtered" without any specific order. – sharptooth Jun 3 '13 at 11:14
    
@sharptooth If you perform a select after an orderby, the select doesn't change the order of the results. (Although I could be wrong, maybe LINQ-to-objects provides more of a guarantee here than LINQ-to-SQL does.) – Rawling Jun 3 '13 at 11:20
    
@Rawling: How is that guaranteed? – sharptooth Jun 3 '13 at 11:20
    
@sharptooth I'm used to LINQ-to-objects where it's definitely true, and I'd honestly be very surprised if the same wasn't true for LINQ-to-SQL, but it seems obvious enough that I can't think how to prove it :-/ – Rawling Jun 3 '13 at 11:22
IQueryable<Guid> GetOrdered(IQueryable<Guid> ids, bool descending = false)
{
    var results = from id in ids join storedId in storedIds on id equals storedId.Id
                  select id;

    if (descending)
       results = results.OrderByDescending(o => o.Something);
    else
       results = results.OrderBy(o => o.Something);

    return results;
}

This is kinda standard stuff.

However, if you need to order by something you don't actually select, you need to split the query into multiple statements. You know, construct the query step by step, like we did it back in the ADO days. First do the ordering and then specify the columns for the select. Because you don't materialize the results, it should generate only a single sql query.

It might look like this.

IQueryable<Guid> GetOrdered(IQueryable<Guid> ids, bool descending = false)
{
    var results = storedIds.Where(somecondition);        
    if (descending)
       results = results.OrderByDescending(o => o.Something);
    else
       results = results.OrderBy(o => o.Something);

    return results.Select(o => o.Id);
}

About your last sentence..

but the problem is I will often have a non-numeric column as one by which I need my set ordered.

That's true. There might be a way to overcome this (like use some factory that would generate the value to compare to based on some input), but that's really an overkill for a task like this. Sometimes the easiest solution is the best. Too generic ways of doing things can smell really bad. Don't overthink the problem ;)

share|improve this answer
1  
This is exactly like the solution he said he couldn't use. – Magnus Jun 3 '13 at 11:39

To achieve conditional OrderBy in Linq, you could do something like this:

var flag = sortOrder == "asc";

result.OrderBy(o => flag ? o.Something: "").ThenByDescending(o => flag ? "" : o.Something).ToList();

Works for me.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.