"Ordina per" multiplo in LINQ
-
08-07-2019 - |
Domanda
Ho due tabelle, film
e categorie
, e ottengo prima un elenco ordinato per IDCategoria e poi per Nome .
La tabella dei filmati ha tre colonne, ID, nome e ID categoria . La tabella delle categorie due ha colonne, ID e nome .
Ho provato qualcosa di simile al seguente, ma non ha funzionato.
var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })
Soluzione
Questo dovrebbe funzionare per te:
var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)
Altri suggerimenti
Usando LINQ non-lambda, con sintassi delle query, puoi farlo:
var movies = from row in _db.Movies
orderby row.Category, row.Name
select row;
[MODIFICA per indirizzare commento] Per controllare l'ordinamento, utilizzare le parole chiave crescente
(che è l'impostazione predefinita e quindi non particolarmente utile) o decrescente
, in questo modo:
var movies = from row in _db.Movies
orderby row.Category descending, row.Name
select row;
Aggiungi " nuovo " ;:
var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })
Funziona sulla mia scatola. Restituisce qualcosa che può essere usato per ordinare. Restituisce un oggetto con due valori.
Simile, ma diverso dall'ordinamento per colonna combinata, come segue.
var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))
usa la seguente riga su DataContext per registrare l'attività SQL su DataContext sulla console - quindi puoi vedere esattamente cosa richiedono le tue istruzioni linq dal database:
_db.Log = Console.Out
Le seguenti istruzioni LINQ:
var movies = from row in _db.Movies
orderby row.CategoryID, row.Name
select row;
E
var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);
produce il seguente SQL:
SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]
Considerando che, ripetendo un OrderBy in Linq, sembra invertire l'output SQL risultante:
var movies = from row in _db.Movies
orderby row.CategoryID
orderby row.Name
select row;
E
var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);
produce il seguente SQL (Nome e CategoryId sono cambiati):
SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID
Ho creato alcuni metodi di estensione (sotto), quindi non devi preoccuparti se un IQueryable è già stato ordinato o meno. Se vuoi ordinare per più proprietà, fallo come segue:
// 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);
Ciò è particolarmente utile se si crea l'ordine in modo dinamico, ad es. da un elenco di proprietà da ordinare.
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);
}
}
}
Esiste almeno un altro modo per farlo usando LINQ, sebbene non sia il più semplice.
Puoi farlo utilizzando il metodo OrberBy ()
che utilizza un IComparer
. Per prima cosa devi
implementare un IComparer
per la classe Movie
come questa:
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);
}
}
}
Quindi puoi ordinare i film con la seguente sintassi:
var movies = _db.Movies.OrderBy(item => item, new MovieComparer());
Se devi cambiare l'ordine in ordine decrescente per uno degli articoli, cambia la xey all'interno del Compare ()
metodo del MovieComparer
di conseguenza.
Se usi un repository generico
> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();
altro
> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();