LINQ中的多个“order by”

Multiple “order by” in LINQ

我有两张表:moviescategories,我先按categoryID排序,然后按名称排序。

Movie表有三列:ID、名称和CategoryID。类别表2有列、ID和名称。

我试过以下的方法,但没用。

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


这应该对你有用:

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


使用非lambda查询语法linq,可以执行以下操作:

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

[编辑地址注释]要控制排序顺序,请使用关键字ascending(这是默认值,因此不是特别有用)或descending,如下所示:

1
2
3
var movies = from row in _db.Movies
             orderby row.Category descending, row.Name
             select row;


添加"新":

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

在我的盒子里可以用。它会返回一些可用于排序的内容。它返回具有两个值的对象。

类似,但不同于按组合列排序,如下所示。

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


在DataContext上使用以下行将DataContext上的SQL活动记录到控制台-然后您可以确切地看到LINQ语句从数据库请求什么:

1
_db.Log = Console.Out

以下LINQ语句:

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

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

生成以下SQL:

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

然而,在linq中重复orderby,似乎会反转产生的SQL输出:

1
2
3
4
var movies = from row in _db.Movies
             orderby row.CategoryID
             orderby row.Name
             select row;

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

生成以下SQL(名称和CategoryID已切换):

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

我已经创建了一些扩展方法(如下),因此您不必担心iQueryable是否已经被订购。如果要按多个属性排序,请执行以下操作:

1
2
3
// 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);

如果您动态地创建排序(例如,从要排序的属性列表中创建排序),这尤其有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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);
        }
    }
}


使用LINQ至少还有一种方法可以做到这一点,尽管这不是最简单的方法。您可以通过使用IComparerOrberBy()方法来实现。首先你需要为Movie类实现一个IComparer,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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);
        }
    }
}

然后您可以使用以下语法订购电影:

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

如果需要将其中一个项目的顺序切换为降序,只需切换Compare()中的x和y即可。相应的MovieComparer方法。


如果使用通用存储库

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

其他的

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