Множественный "заказ по" в LINQ - PullRequest
1482 голосов
/ 18 ноября 2008

У меня есть две таблицы, movies и categories, и я получаю упорядоченный список сначала categoryID , а затем Имя .

Таблица фильмов имеет три столбца: ID, Имя и CategoryID . Таблица категорий 2 имеет столбцы, ID и Имя .

Я попробовал что-то вроде следующего, но это не сработало.

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

Ответы [ 7 ]

2677 голосов
/ 18 ноября 2008

Это должно работать для вас:

var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)
575 голосов
/ 30 сентября 2010

Используя не-лямбду, синтаксис запроса LINQ, вы можете сделать это:

var movies = from row in _db.Movies 
             orderby row.Category, row.Name
             select row;

[РЕДАКТИРОВАТЬ к адресному комментарию] Чтобы управлять порядком сортировки, используйте ключевые слова ascending (который используется по умолчанию и поэтому не особенно полезен) или descending, например:

var movies = from row in _db.Movies 
             orderby row.Category descending, row.Name
             select row;
71 голосов
/ 22 июня 2011

Добавить "новый":

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

Это работает на моей коробке. Он возвращает что-то, что можно использовать для сортировки. Возвращает объект с двумя значениями.

Аналогично, но отличается от сортировки по объединенному столбцу следующим образом.

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))
25 голосов
/ 19 февраля 2016

используйте следующую строку в вашем DataContext, чтобы записать активность SQL в DataContext на консоль - тогда вы сможете точно увидеть, что ваши операторы linq запрашивают из базы данных:

_db.Log = Console.Out

Следующие операторы LINQ:

var movies = from row in _db.Movies 
             orderby row.CategoryID, row.Name
             select row;

И

var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);

производит следующий SQL:

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]

Принимая во внимание, что повторение OrderBy в Linq, по-видимому, обращает результирующий вывод SQL:

var movies = from row in _db.Movies 
             orderby row.CategoryID
             orderby row.Name
             select row;

И

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

создает следующий SQL (имя и CategoryId переключаются):

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID
18 голосов
/ 08 июня 2017

Я создал несколько методов расширения (ниже), так что вам не нужно беспокоиться, заказан ли IQueryable или нет. Если вы хотите заказать по нескольким свойствам, просто сделайте это следующим образом:

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

Это особенно полезно, если вы создаете заказ динамически, например из списка свойств для сортировки.

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);
        }
    }
}
13 голосов
/ 03 апреля 2015

Существует по крайней мере еще один способ сделать это с помощью LINQ, хотя и не самый простой. Вы можете сделать это, используя метод OrberBy(), который использует IComparer. Сначала вам нужно реализовать IComparer для класса Movie следующим образом:

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

Затем вы можете заказать фильмы со следующим синтаксисом:

var movies = _db.Movies.OrderBy(item => item, new MovieComparer());

Если вам нужно переключить порядок убывания для одного из элементов, просто переключите x и y внутри Compare() метод MovieComparer соответственно.

1 голос
/ 17 июля 2018

Если использовать общий репозиторий

> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();

еще

> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();
...