当前位置:  开发笔记 > 编程语言 > 正文

LINQ中的多个"order by"

如何解决《LINQ中的多个"orderby"》经验,为你挑选了6个好方法。

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

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

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

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

Nathan W.. 2756

这应该适合你:

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

@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认同)

谢谢你的回答当然......但不是`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认同)


Scott Staffo.. 584

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

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

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

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

@Lodewijk:我相信你完全倒退了.你的例子最终将row.Name作为主列和row.Category secondary,它相当于`_db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name)`.您提供的两个片段彼此相同,而不是OP. (9认同)

使用Linq的SQL语法的唯一缺点是并非所有函数都受支持,大多数但不是全部 (6认同)


Alex.. 71

添新":

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

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

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

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

将其用于数字时要小心. (21认同)

您可以根据需要使用OrderByDescending和ThenBy,或OrderBy和ThenByDescending. (7认同)

当我尝试按匿名类型排序时,我得到一个带有消息"至少有一个对象必须实现IComparable"的ArgumentException.我看到其他人在这样做时必须声明一个比较器.请参阅/sf/ask/17360801/. (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认同)


Oliver Slay.. 28

使用DataContext上的以下行将DataContext上的SQL活动记录到控制台 - 然后您可以确切地看到您的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]

然而,在Linq中重复OrderBy似乎会反转生成的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


sjkm.. 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);

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

public static class IQueryableExtension
{
    public static bool IsOrdered(this IQueryable queryable) {
        if(queryable == null) {
            throw new ArgumentNullException("queryable");
        }

        return queryable.Expression.Type == typeof(IOrderedQueryable);
    }

    public static IQueryable SmartOrderBy(this IQueryable queryable, Expression> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable SmartOrderByDescending(this IQueryable queryable, Expression> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}


prudentcoder.. 15

使用LINQ至少还有一种方法可以做到这一点,尽管不是最简单的方法.您可以使用使用的OrberBy()方法来完成IComparer.首先,你需要IComparer为这样的Movie类实现一个:

public class MovieComparer : IComparer
{
    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());

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



1> Nathan W..:

这应该适合你:

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


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

2> Scott Staffo..:

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

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

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

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


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

3> Alex..:

添新":

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

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

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

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


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

4> Oliver Slay..:

使用DataContext上的以下行将DataContext上的SQL活动记录到控制台 - 然后您可以确切地看到您的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]

然而,在Linq中重复OrderBy似乎会反转生成的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



5> sjkm..:

我已经创建了一些扩展方法(如下所示),因此您不必担心是否已经订购了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(this IQueryable queryable) {
        if(queryable == null) {
            throw new ArgumentNullException("queryable");
        }

        return queryable.Expression.Type == typeof(IOrderedQueryable);
    }

    public static IQueryable SmartOrderBy(this IQueryable queryable, Expression> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable;
            return orderedQuery.ThenBy(keySelector);
        } else {
            return queryable.OrderBy(keySelector);
        }
    }

    public static IQueryable SmartOrderByDescending(this IQueryable queryable, Expression> keySelector) {
        if(queryable.IsOrdered()) {
            var orderedQuery = queryable as IOrderedQueryable;
            return orderedQuery.ThenByDescending(keySelector);
        } else {
            return queryable.OrderByDescending(keySelector);
        }
    }
}



6> prudentcoder..:

使用LINQ至少还有一种方法可以做到这一点,尽管不是最简单的方法.您可以使用使用的OrberBy()方法来完成IComparer.首先,你需要IComparer为这样的Movie类实现一个:

public class MovieComparer : IComparer
{
    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());

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

推荐阅读
拾味湖
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有