LINQ OrderBy vs ThenBy

时间:2010-09-21 11:51:57

标签: linq

任何人都可以解释之间的区别:

tmp = invoices.InvoiceCollection
              .OrderBy(sort1 => sort1.InvoiceOwner.LastName)
              .OrderBy(sort2 => sort2.InvoiceOwner.FirstName)
              .OrderBy(sort3 => sort3.InvoiceID);

tmp = invoices.InvoiceCollection
              .OrderBy(sort1 => sort1.InvoiceOwner.LastName)
              .ThenBy(sort2 => sort2.InvoiceOwner.FirstName)
              .ThenBy(sort3 => sort3.InvoiceID);

如果我希望按3项数据订购,哪种方法正确?

4 个答案:

答案 0 :(得分:198)

肯定使用ThenBy而不是多次OrderBy来电。 (我假设你问题中的一个片段是用ThenBy。在撰写本文时,两个片段是相同的。)

我会建议:

tmp = invoices.InvoiceCollection
              .OrderBy(o => o.InvoiceOwner.LastName)
              .ThenBy(o => o.InvoiceOwner.FirstName)
              .ThenBy(o => o.InvoiceID);

请注意每次都可以使用相同的名称。这也相当于:

tmp = from o in invoices.InvoiceCollection
      orderby o.InvoiceOwner.LastName,
              o.InvoiceOwner.FirstName,
              o.InvoiceID
      select o;

如果您多次拨打OrderBy,它会有效地将序列重新排序三次......所以最终的呼叫将有效地成为主导呼叫。你可以(在LINQ to Objects中)写

foo.OrderBy(x).OrderBy(y).OrderBy(z)

这相当于

foo.OrderBy(z).ThenBy(y).ThenBy(x)

因为排序顺序稳定,但绝对不应该:

  • 很难阅读
  • 效果不佳(因为它重新排序整个序列)
  • 它可能在其他提供程序中工作(例如LINQ to SQL)
  • 基本上不是OrderBy设计使用的方式。

OrderBy的要点是提供“最重要的”排序预测;然后使用ThenBy(重复)指定二级,三级等排序预测。

实际上,可以这样考虑:OrderBy(...).ThenBy(...).ThenBy(...)允许您为任意两个对象构建单个复合比较,然后使用该复合比较对序列进行一次。这几乎可以肯定你想要的。

答案 1 :(得分:2)

我发现这种区别在尝试以通用方式构建查询时很烦人,所以我做了一个小帮手,以正确的顺序生成OrderBy / ThenBy,因为你喜欢的种类很多。

public class EFSortHelper
{
  public static EFSortHelper<TModel> Create<TModel>(IQueryable<T> query)
  {
    return new EFSortHelper<TModel>(query);
  }
}  

public class EFSortHelper<TModel> : EFSortHelper
{
  protected IQueryable<TModel> unsorted;
  protected IOrderedQueryable<TModel> sorted;

  public EFSortHelper(IQueryable<TModel> unsorted)
  {
    this.unsorted = unsorted;
  }

  public void SortBy<TCol>(Expression<Func<TModel, TCol>> sort, bool isDesc = false)
  {
    if (sorted == null)
    {
      sorted = isDesc ? unsorted.OrderByDescending(sort) : unsorted.OrderBy(sort);
      unsorted = null;
    }
    else
    {
      sorted = isDesc ? sorted.ThenByDescending(sort) : sorted.ThenBy(sort)
    }
  }

  public IOrderedQueryable<TModel> Sorted
  {
    get
    {
      return sorted;
    }
  }
}

根据您的使用情况,有很多方法可以使用它,但是如果您例如将排序列和方向列表作为字符串和bool传递,您可以循环它们并在像这样的开关中使用它们:

var query = db.People.AsNoTracking();
var sortHelper = EFSortHelper.Create(query);
foreach(var sort in sorts)
{
  switch(sort.ColumnName)
  {
    case "Id":
      sortHelper.SortBy(p => p.Id, sort.IsDesc);
      break;
    case "Name":
      sortHelper.SortBy(p => p.Name, sort.IsDesc);
      break;
      // etc
  }
}

var sortedQuery = sortHelper.Sorted;

sortedQuery中的结果按照所需的顺序排序,而不是像其他答案一样反复尝试。

答案 2 :(得分:1)

如果您想要排序多个字段,请转到ThenBy:

像这样

list.OrderBy(personLast => person.LastName)
            .ThenBy(personFirst => person.FirstName)

答案 3 :(得分:0)

是的,如果您正在玩多个键,则不应使用多个OrderBy。 然后是更安全的赌注,因为它将在OrderBy之后执行。