LINQ中的多个"order by"

Sas*_*sha 1537 linq sql-order-by

我有两个表,movies并且categories,我首先按类别ID获取有序列表,然后按名称获取.

影片表有三列,ID,Name和CategoryID.类别表2包含列,ID和名称.

我尝试了类似下面的内容,但它没有用.

var movies = _db.Movies.OrderBy( m => { m.CategoryID, m.Name })
Run Code Online (Sandbox Code Playgroud)

Nat*_*n W 2756

这应该适合你:

var movies = _db.Movies.OrderBy(c => c.Category).ThenBy(n => n.Name)
Run Code Online (Sandbox Code Playgroud)

  • @devendra,结果是不同的,因为第二个"OrderBy"工作于第一个"OrderBy"的结果集合并重新排序其项目 (143认同)
  • 在不知道`ThenBy`的情况下,我怎么一直走了?!(__编辑:__看起来像是在.NET 4.0中引入的,它解释了它是如何在我不知不觉中滑过我的.) (66认同)
  • 自从LINQ被添加以来,这一直存在.这个答案是.NET 4.0之前的. (13认同)
  • 是的,我的结论是太仓促地基于3.5不在[文档页面]的版本下拉列表中(http://msdn.microsoft.com/en-us/library/bb534743.aspx); 我应该一直向下看版本信息.谢谢你的纠正.:) (10认同)
  • 请注意:`.ThenBy()` = 升序,`.ThenByDescending()` = 降序!!(听起来很合乎逻辑,是吧?) (9认同)
  • 谢谢你的回答当然......但不是`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"为什么结果不同? (3认同)
  • ThenBy操作IOrderedEnumerable(由OrderBy返回) (2认同)

Sco*_*ord 584

使用非lambda查询语法LINQ,您可以这样做:

var movies = from row in _db.Movies 
             orderby row.Category, row.Name
             select row;
Run Code Online (Sandbox Code Playgroud)

[EDIT来解决评论]要控制排序顺序,请使用关键字ascending(这是默认值,因此不是特别有用),或者descending像这样:

var movies = from row in _db.Movies 
             orderby row.Category descending, row.Name
             select row;
Run Code Online (Sandbox Code Playgroud)

  • @Lodewijk:我相信你完全倒退了.你的例子最终将row.Name作为主列和row.Category secondary,它相当于`_db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)`.您提供的两个片段彼此相同,而不是OP. (9认同)
  • 使用Linq的SQL语法的唯一缺点是并非所有函数都受支持,大多数但不是全部 (6认同)

Ale*_*lex 71

添新":

var movies = _db.Movies.OrderBy( m => new { m.CategoryID, m.Name })
Run Code Online (Sandbox Code Playgroud)

这适用于我的盒子.它确实返回了可用于排序的东西.它返回一个具有两个值的对象.

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

var movies = _db.Movies.OrderBy( m => (m.CategoryID.ToString() + m.Name))
Run Code Online (Sandbox Code Playgroud)

  • 将其用于数字时要小心. (21认同)
  • 您可以根据需要使用OrderByDescending和ThenBy,或OrderBy和ThenByDescending. (7认同)
  • 当我尝试按匿名类型排序时,我得到一个带有消息"至少有一个对象必须实现IComparable"的ArgumentException.我看到其他人在这样做时必须声明一个比较器.请参阅/sf/ask/724980511/. (7认同)
  • 我很确定`.OrderBy(m => new {m.CategoryID,m.Name})`和`.OrderBy(m => new {m.Name,m.CategoryID})`会产生相同的结果而不是尊重预期的优先权.它有时似乎只是巧合地给你你想要的顺序.另外,如果CategoryID是`int`,`m.CategoryID.ToString()+ m.Name`将产生不正确的排序.例如,id = 123,name = 5times的东西将出现在id = 1234之后,name = something而不是之前.在进行int比较时进行字符串比较也效率不高. (5认同)
  • 这是绝对错误的.使用没有ICompariable实现的新匿名类型进行排序是行不通的,因为匿名类型的属性没有顺序.它不知道是先对CategoryID进行排序还是首先对Name进行排序,更不用说如果要按相反的顺序对它们进行排序. (4认同)
  • “ OrderBy(m => new {m.CategoryID,m.Name})”不起作用,它抛出异常“至少一个对象必须实现IComparable”。 (2认同)
  • 具有匿名类型`m => new {m.CategoryID,m.Name}`的技术不适用于Linq-to-Objects__,因为正如上面的评论中已经提到的,匿名类型既不是IComparable也不是IComparable <>。它可能会也可能不会与其他LINQ提供程序(Linq-to-Sql?)一起使用,这取决于所讨论的“引擎”是否具有将包含匿名类型的表达式树转换为有意义的东西的方式(例如有效的SQL查询)。 (2认同)

Oli*_*lay 28

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

_db.Log = Console.Out
Run Code Online (Sandbox Code Playgroud)

以下LINQ语句:

var movies = from row in _db.Movies 
             orderby row.CategoryID, row.Name
             select row;
Run Code Online (Sandbox Code Playgroud)

var movies = _db.Movies.OrderBy(m => m.CategoryID).ThenBy(m => m.Name);
Run Code Online (Sandbox Code Playgroud)

产生以下SQL:

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].CategoryID, [t0].[Name]
Run Code Online (Sandbox Code Playgroud)

然而,在Linq中重复OrderBy似乎会反转生成的SQL输出:

var movies = from row in _db.Movies 
             orderby row.CategoryID
             orderby row.Name
             select row;
Run Code Online (Sandbox Code Playgroud)

var movies = _db.Movies.OrderBy(m => m.CategoryID).OrderBy(m => m.Name);
Run Code Online (Sandbox Code Playgroud)

产生以下SQL(Name和CategoryId被切换):

SELECT [t0].ID, [t0].[Name], [t0].CategoryID
FROM [dbo].[Movies] as [t0]
ORDER BY [t0].[Name], [t0].CategoryID
Run Code Online (Sandbox Code Playgroud)


sjk*_*jkm 21

我已经创建了一些扩展方法(如下所示),因此您不必担心是否已经订购了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);
Run Code Online (Sandbox Code Playgroud)

如果您从要排序的属性列表中动态创建排序,这将特别有用.

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这个答案是黄金!我将对 queryable.IsOrdered() 的检查与这篇文章的答案结合起来,以获得一个采用排序方向的单一方法:/sf/ask/27209591/ (4认同)
  • 这样 Linq 的实现应该放在第一位!OrderBy 设计得很糟糕...... (3认同)

pru*_*der 15

使用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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

var movies = _db.Movies.OrderBy(item => item, new MovieComparer());
Run Code Online (Sandbox Code Playgroud)

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

  • 自 2012 年(.NET 4.5 版)起,您不必自己创建类“MovieComparer”;相反,您可以执行 `_db.Movies.OrderBy(item =&gt; item, Comparer&lt;Movie&gt;.Create((x, y) =&gt; { if (x.CategoryId == y.CategoryId) { return x.Name.CompareTo( y.Name); } else { return x.CategoryId.CompareTo(y.CategoryId); } }));`. 当然,如果你更喜欢将逻辑写成一个表达式,而不是 `if`...`else`,那么 lamda `(x, y) =&gt; expr` 可以更简单。 (2认同)

Sai*_*ume 6

如果使用通用存储库

> lstModule = _ModuleRepository.GetAll().OrderBy(x => new { x.Level,
> x.Rank}).ToList();
Run Code Online (Sandbox Code Playgroud)

别的

> _db.Module.Where(x=> ......).OrderBy(x => new { x.Level, x.Rank}).ToList();
Run Code Online (Sandbox Code Playgroud)

  • 匿名表达式将由实体框架核心在本地解析。无法翻译 LINQ 表达式,将在本地计算。 (2认同)