Plusieurs «commander par» dans LINQ
-
08-07-2019 - |
Question
J'ai deux tables, films
et catégories
, et je reçois une liste ordonnée par categoryID d'abord, puis par Nom .
La table de films comporte trois colonnes, ID, Nom et ID de catégorie . La table de catégories deux comporte des colonnes, ID et Nom .
J'ai essayé quelque chose comme ce qui suit, mais cela n'a pas fonctionné.
var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })
La solution
Cela devrait fonctionner pour vous:
var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)
Autres conseils
En utilisant LINQ, une syntaxe de requête non lambda, vous pouvez le faire:
var movies = from row in _db.Movies
orderby row.Category, row.Name
select row;
[EDIT to address comment] Pour contrôler l'ordre de tri, utilisez les mots-clés croissant
(par défaut, donc pas particulièrement utile) ou décroissant
, comme suit:
var movies = from row in _db.Movies
orderby row.Category descending, row.Name
select row;
Ajouter "nouveau":
var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })
Cela fonctionne sur ma boîte. Il retourne quelque chose qui peut être utilisé pour trier. Il retourne un objet avec deux valeurs.
Similaire, mais différent du tri par colonne combinée, comme suit.
var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))
utilisez la ligne suivante sur votre DataContext pour consigner l'activité SQL sur le DataContext sur la console. Vous pouvez alors voir exactement ce que vos instructions linq demandent à la base de données:
_db.Log = Console.Out
Les instructions LINQ suivantes:
var movies = from row in _db.Movies
orderby row.CategoryID, row.Name
select row;
ET
var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);
produit le code SQL suivant:
SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]
Alors que répéter un OrderBy dans Linq semble renverser la sortie SQL résultante:
var movies = from row in _db.Movies
orderby row.CategoryID
orderby row.Name
select row;
ET
var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);
produit le code SQL suivant (Name et CategoryId sont commutés):
SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID
J'ai créé des méthodes d'extension (ci-dessous) pour que vous n'ayez pas à vous inquiéter si un IQueryable est déjà commandé ou non. Si vous souhaitez commander par plusieurs propriétés, procédez comme suit:
// We do not have to care if the queryable is already sorted or not.
// The order of the Smart* calls defines the order priority
queryable.SmartOrderBy(i => i.Property1).SmartOrderByDescending(i => i.Property2);
Ceci est particulièrement utile si vous créez la commande de manière dynamique, par exemple. dans une liste de propriétés à trier.
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);
}
}
}
Il existe au moins une autre façon de faire cela en utilisant LINQ, bien que ce ne soit pas la plus simple.
Vous pouvez le faire en utilisant la méthode OrberBy ()
qui utilise un IComparer
. Vous devez d'abord
implémenter un IComparer
pour la classe Movie
comme ceci:
public class MovieComparer : IComparer<Movie>
{
public int Compare(Movie x, Movie y)
{
if (x.CategoryId == y.CategoryId)
{
return x.Name.CompareTo(y.Name);
}
else
{
return x.CategoryId.CompareTo(y.CategoryId);
}
}
}
Vous pouvez ensuite commander les films avec la syntaxe suivante:
var movies = _db.Movies.OrderBy(item => item, new MovieComparer());
Si vous avez besoin de passer en ordre décroissant pour l'un des éléments, il suffit de changer le x et le y à l'intérieur du Compare ()
.
méthode du MovieComparer
en conséquence.
Si vous utilisez un référentiel générique
> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();
sinon
> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();