Language Integrated Query (LINQ) provides a powerful way to query and manipulate data in .NET. One common requirement when working with data is sorting it based on multiple criteria. In this tutorial, we will explore how to use LINQ to sort data by multiple fields, also known as multi-sorting or secondary sorting.
Introduction to LINQ Sorting
Before diving into multi-sorting, let’s cover the basics of LINQ sorting. The OrderBy
method is used to sort a sequence of values in ascending order. You can specify a key selector function that determines which property of the object to use for sorting.
var movies = _db.Movies.OrderBy(m => m.Name);
This code sorts the movies
collection by the Name
property in ascending order.
Multi-Sorting with LINQ
To sort data by multiple fields, you can chain the ThenBy
method after the initial OrderBy
call. The ThenBy
method specifies a secondary sorting criterion that is applied when two or more items have the same value for the primary sorting criterion.
var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);
In this example, the movies
collection is first sorted by the CategoryID
property, and then by the Name
property. This means that all movies with the same CategoryID
will be grouped together and sorted by their Name
.
Query Syntax
You can also use query syntax to perform multi-sorting. The orderby
keyword is used to specify the primary sorting criterion, and subsequent orderby
keywords are used for secondary sorting.
var movies = from row in _db.Movies
orderby row.CategoryID, row.Name
select row;
This query syntax is equivalent to the method syntax example above.
Controlling Sort Order
By default, LINQ sorts data in ascending order. You can use the descending
keyword to sort data in descending order. For secondary sorting criteria, you can use the ThenByDescending
method.
var movies = from row in _db.Movies
orderby row.CategoryID descending, row.Name
select row;
This code sorts the movies
collection by the CategoryID
property in descending order, and then by the Name
property in ascending order.
Dynamic Sorting
In some cases, you may need to dynamically specify the sorting criteria based on user input or other factors. You can use extension methods to create a flexible sorting mechanism.
public static class IQueryableExtension
{
public static bool IsOrdered<T>(this IQueryable<T> queryable) {
if (queryable == null) {
throw new ArgumentNullException("queryable");
}
return queryable.Expression.Type == typeof(IOrderedQueryable<T>);
}
public static IQueryable<T> SmartOrderBy<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
if (queryable.IsOrdered()) {
var orderedQuery = queryable as IOrderedQueryable<T>;
return orderedQuery.ThenBy(keySelector);
} else {
return queryable.OrderBy(keySelector);
}
}
public static IQueryable<T> SmartOrderByDescending<T, TKey>(this IQueryable<T> queryable, Expression<Func<T, TKey>> keySelector) {
if (queryable.IsOrdered()) {
var orderedQuery = queryable as IOrderedQueryable<T>;
return orderedQuery.ThenByDescending(keySelector);
} else {
return queryable.OrderByDescending(keySelector);
}
}
}
These extension methods allow you to dynamically add sorting criteria to a query without worrying about whether the query is already sorted or not.
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);
This code adds two sorting criteria to the queryable
collection: first by Property1
in ascending order, and then by Property2
in descending order.
Conclusion
In this tutorial, we have covered the basics of LINQ multi-sorting, including how to use the OrderBy
and ThenBy
methods to sort data by multiple fields. We have also explored query syntax and controlling sort order using the descending
keyword. Additionally, we have seen how to create a flexible sorting mechanism using extension methods.