У меня есть две таблицы, movies
и categories
я получаю упорядоченный список сначала по categoryID, а затем по имени .
Таблица фильмов имеет три столбца ID, Имя и CategoryID . Таблица категорий имеет два столбца ID и Имя .
Я попробовал что-то вроде следующего, но это не сработало.
var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })
Это должно работать для вас:
var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)
Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name)
чтобы использовать Var movies = _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)
2 раза "orderBy", почему результат отличается? ThenBy
?! ( Изменить: похоже, что он был введен в .NET 4.0, который объясняет, как он незаметно проскользнул мимо меня.)Используя не лямбда, синтаксис запроса 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;
_db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)
. Более правильным являетсяfrom row in _db.Movies orderby row.Category descending orderby row.Name select row
_db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)
. Два предоставленных вами фрагмента эквивалентны друг другу, а не ОП. Добавить новое":
var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })
Это работает на моей коробке. Он возвращает что-то, что можно использовать для сортировки. Возвращает объект с двумя значениями.
Аналогично, но отличается от сортировки по объединенному столбцу следующим образом.
var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))
.OrderBy( m => new { m.CategoryID, m.Name })
и .OrderBy( m => new { m.Name, m.CategoryID })
получу те же результаты, а не соблюдение намеченного приоритета. Иногда может показаться, что вы заказываете то, что вам нужно, по стечению обстоятельств. Кроме того, m.CategoryID.ToString() + m.Name
будут получены неправильные заказы, если CategoryID является int
. Например, что-то с id = 123, name = 5times появится после id = 1234, name = что-то вместо прежнего. Также неэффективно проводить сравнения строк, где могут происходить сравнения int. Есть по крайней мере еще один способ сделать это с помощью 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
соответственно.
MovieComparer
самостоятельно; вместо этого вы можете сделать _db.Movies.OrderBy(item => item, Comparer<Movie>.Create((x, y) => { if (x.CategoryId == y.CategoryId) { return x.Name.CompareTo(y.Name); } else { return x.CategoryId.CompareTo(y.CategoryId); } }));
. Конечно, если вы предпочитаете писать логику в виде одного выражения вместо if
... else
, тогда лямда (x, y) => expr
может быть проще. используйте следующую строку в вашем 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 (Name и CategoryId переключаются):
SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID
Я создал несколько методов расширения (ниже), поэтому вам не нужно беспокоиться о том, заказан ли 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);
}
}
}
nullable datetime
Если использовать общий репозиторий
> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();
еще
> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();