LINQ OrderBy与ThenBy
任何人都可以解释之间的区别是什么:
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项数据进行sorting,哪种方法是正确的?
你一定要使用ThenBy
而不是多个OrderBy
调用。 (我假设你的问题中的一个片段是用ThenBy
,在写这篇文章的时候,这两个片段是相同的。)
我会build议这样的:
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
,它将完全重新sorting序列三次…所以最终的调用将是有效的。 你可以 (在LINQ to Objects)编写
foo.OrderBy(x).OrderBy(y).OrderBy(z)
这将相当于
foo.OrderBy(z).ThenBy(y).ThenBy(x)
因为sorting顺序是稳定的,但绝对不应该:
- 这很难阅读
- 它performance不佳(因为它重新sorting整个序列)
- 它可能不适用于其他提供者(例如,LINQ to SQL)
- 这基本上不是
OrderBy
devise原理。
OrderBy
的要点是提供“最重要的”sorting投影; 然后使用ThenBy
(重复)来指定二级,三级等sorting投影。
实际上,可以这样想: OrderBy(...).ThenBy(...).ThenBy(...)
允许您为任何两个对象构build一个复合比较,然后使用该复合比较。 这几乎可以肯定你想要的。
我发现这个区别在试图以通用的方式构build查询时很烦人,所以我做了一个小小的帮手来按照正确的顺序生成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; } } }
有很多方法可以使用这取决于你的用例,但是如果你是例如传递一个sorting列和方向的列表作为string和布尔,你可以循环它们,并使用它们在一个开关,如:
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
的结果按照所需的顺序sorting,而不是一遍又一遍,因为这里的其他答案要注意。
如果你想sorting多个字段然后去ThenBy:
喜欢这个
list.OrderBy(personLast => person.LastName) .ThenBy(personFirst => person.FirstName)
是的,如果您使用多个键,则不应使用多个OrderBy。 ThenBy是更安全的赌注,因为它将在OrderBy之后执行。