sql-order-by - Più "ordina per" in LINQ




(7)

Ho due tabelle, movies e categories e ottengo una lista ordinata per categoryID prima e poi per Name .

La tabella del film ha tre colonne, ID, Nome e IDCategoria . 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 })

Answers

utilizzare la seguente riga sul DataContext per registrare l'attività SQL su DataContext sulla console, quindi è possibile visualizzare esattamente quali richieste del proprio linq richiedono 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);

produrre 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);

produrre il seguente SQL (Nome e CategoryId sono commutati):

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) in modo da non doversi preoccupare se un IQueryable è già 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'ordinamento in modo dinamico, 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);
        }
    }
}

Se si utilizza 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();

C'è almeno un altro modo per farlo usando LINQ, sebbene non sia il più semplice. Puoi farlo usando il metodo OrberBy() che usa un OrberBy() . Per prima cosa devi implementare un IComparer per la classe Movie come questo:

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 è necessario passare l'ordine alla discesa per uno degli elementi, basta cambiare di conseguenza la xey all'interno del metodo Compare() di MovieComparer .


Questo dovrebbe funzionare per te:

var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)

Aggiungere nuova":

var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })

Funziona sulla mia scatola. Ritorna qualcosa che può essere usato per ordinare. Restituisce un oggetto con due valori.

Simile, ma diverso per l'ordinamento da una colonna combinata, come segue.

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))

Nella mia applicazione ho scoperto che l'utilizzo di LINQ to Dataset con l'estensione AsEnumerable () per DataTable come suggerito nella risposta era estremamente lento. Se ti interessa ottimizzare la velocità, usa la libreria Json.Net di James Newtonking ( http://james.newtonking.com/json/help/index.html )

// Serialize the DataTable to a json string
string serializedTable = JsonConvert.SerializeObject(myDataTable);    
Jarray dataRows = Jarray.Parse(serializedTable);

// Run the LINQ query
List<JToken> results = (from row in dataRows
                    where (int) row["ans_key"] == 42
                    select row).ToList();

// If you need the results to be in a DataTable
string jsonResults = JsonConvert.SerializeObject(results);
DataTable resultsTable = JsonConvert.DeserializeObject<DataTable>(jsonResults);




linq sql-order-by