简体   繁体   English

如何有选择地反转Linq-to-Sql中的排序顺序?

[英]How do I optionally reverse the sorting order in Linq-to-Sql?

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 . 现在,我想向GetOrdered()引入参数,并可选地用orderby descending更改orderby 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. 当然,我可以编写两个相同的查询-一个使用orderby ,另一个使用orderby descending但这意味着代码重复。

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. 或者,我可以对无序集使用子语句,然后像此答案中那样有条件地对其进行排序,但是问题是我然后需要Select()特定列,而后者Select()将呈现无序结果。

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? 在这些条件下如何有条件地颠倒排序顺序?

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. 您知道,一步一步地构造查询,就像我们在ADO时代所做的那样。 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. 因为您没有实现结果,所以它应该只生成一个sql查询。

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 ;) 不要想太多问题;)

To achieve conditional OrderBy in Linq, you could do something like this: 要在Linq中实现有条件的OrderBy,您可以执行以下操作:

var flag = sortOrder == "asc";

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

Works for me. 为我工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM