gpt4 book ai didi

Multiple "order by" in LINQ(LINQ中的多个“order by”)

转载 作者:bug小助手 更新时间:2023-10-25 17:01:02 37 4
gpt4 key购买 nike



I have two tables, movies and categories, and I want to get an ordered list by categoryID first and then by Name.

我有两个表,电影和类别,我想先按CategoryID获得一个排序列表,然后按名称排序。


The movie table has three columns ID, Name and CategoryID.
The category table has two columns ID and Name.

电影表格有三个列ID、NAME和CategoryID。CATEGORY表有两列ID和NAME。


I tried something like the following, but it didn't work.

我尝试了下面这样的方法,但没有奏效。


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

更多回答

Here is why this can't work: The lambda expression in the parentheses is supposed to return a value which can be used to order the items: m.CategoryID is a number which can be used to order the items. But "m.CategoryID, m.Name" doesn't make sense in this context.

这是不起作用的原因:括号中的lambda表达式应该返回一个可用于对项目进行排序的值:m.CategoryID是一个可用于对项目进行排序的数字。但是“m.CategoryID,m.Name”在这种情况下没有意义。

.ThenBy is what you're searching?

.那么这就是你要找的吗?

If by any chance you want to sort them in descending order there here is the way to go.

如果你碰巧想把它们按降序排列,这里有一条路可以走。

优秀答案推荐

This should work for you:

这对你来说应该是可行的:



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


Using non-lambda, query-syntax LINQ, you can do this:

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



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


[EDIT to address comment] To control the sort order, use the keywords ascending (which is the default and therefore not particularly useful) or descending, like so:

[EDIT TO ADDRESS COMMENT]要控制排序顺序,请使用关键字升序(默认设置,因此不是特别有用)或降序,如下所示:



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


Add "new":

添加“新”:



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


That works on my box. It does return something that can be used to sort. It returns an object with two values.

这对我的盒子很管用。它确实返回一些可用于排序的内容。它返回一个具有两个值的对象。



Similar, but different to sorting by a combined column, as follows.

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



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


Use the following line on your DataContext to log the SQL activity on the DataContext to the console - then you can see exactly what your LINQ statements are requesting from the database:

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


_db.Log = Console.Out

The following LINQ statements:

以下LINQ语句:


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

AND


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

produce the following SQL:

生成以下SQL:


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

Whereas, repeating an OrderBy in LINQ, appears to reverse the resulting SQL output:

然而,在LINQ中重复一个OrderBy似乎会颠倒生成的SQL输出:


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

AND


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

produce the following SQL (Name and CategoryId are switched):

生成以下SQL(名称和类别ID互换):


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


I have created some extension methods (below) so you don't have to worry if an IQueryable is already ordered or not. If you want to order by multiple properties just do it as follows:

我已经创建了一些扩展方法(如下),所以你不必担心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);


This is especially helpful if you create the ordering dynamically, f.e. from a list of properties to sort.

如果您动态创建排序,则这尤其有用,F.E.从要排序的属性列表中选择。



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


There is at least one more way to do this using LINQ, although not the easiest.
You can do it by using the OrberBy() method that uses an IComparer. First you need to
implement an IComparer for the Movie class like this:

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



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


Then you can order the movies with the following syntax:

然后,您可以使用以下语法对电影进行排序:



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


If you need to switch the ordering to descending for one of the items just switch the x and y inside the Compare()
method of the MovieComparer accordingly.

如果需要将其中一项的排序切换为降序,只需在MovieCompeller的Compare()方法中相应地切换x和y即可。



If use generic repository

如果使用通用存储库



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


else

其他



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

更多回答

Thanks for the answer of course... But instead of Var movies = _db.Movies.Orderby(c => c.Category).ThenBy(n => n.Name) if I use Var movies = _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name) 2 times "orderBy" why is the result different?

当然,谢谢你的回答……而不是Var Movies.Orderby(c=>c.Category).ThenBy(n=>n.Name)如果我使用Var Movies.Orderby(c=>c.Category).OrderBy(n=>n.Name)2次“orderBy”,为什么结果会不同?

@devendra, result is different because second "OrderBy" works over the collection which is result of first "OrderBy" and reorder its items

@Devendra,结果不同,因为第二个“OrderBy”处理作为第一个“OrderBy”的结果的集合并对其项重新排序

ThenBy operates on IOrderedEnumerable (which is returned by OrderBy)

ThenBy对IOrderedEnumerable(由OrderBy返回)进行操作

Please note: .ThenBy() = Ascending, and .ThenByDescending() = Descending!! (sounds logical, huh?)

请注意:.ThenBy()=升序,.ThenByDescending()=降序!!(听起来合乎逻辑,是吧?)

IQueryable<class> does not contain a definition for ThenBy

IQueryable不包含ThenBy的定义

There's not a way to flip back and forth between descending and non in this syntax is there?

在这种语法中,没有办法在降序和非之间来回切换,是吗?

Actually, your answer is the equivalent to _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name). More correct is from row in _db.Movies orderby row.Category descending orderby row.Name select row

实际上,您的答案等同于_db.Movies.Orderby(c=>c.Category).OrderBy(n=>n.Name)。更正确的是from row in_db。Movies orderby行。类别降序orderby行。名称选择行

@Lodewijk: I believe you have that exactly backwards. Your example will end up having row.Name being the primary column and row.Category secondary, which is the equivalent of _db.Movies.Orderby(c => c.Category).OrderBy(n => n.Name). The two snippets you provide are equivalent to each other, not to the OP's.

@Lodewijk:我相信你完全颠倒了这一点。您的示例最终将拥有作为主列的row.Name和作为次要的row.Category,这等同于_db.Movies.Orderby(c=>c.Category).OrderBy(n=>n.Name)。您提供的两个代码片段彼此等价,而不等同于OP。

The only downside to using the SQL syntax for Linq is that not all of the functions are supported, most but not all

对Linq使用SQL语法的唯一缺点是,并非所有函数都受支持,大多数但不是所有函数都受支持

Be careful when using that for numbers.

在将其用于数字时要小心。

You can use OrderByDescending and ThenBy, or OrderBy and ThenByDescending, depending upon your need.

您可以根据需要使用OrderByDescending和ThenBy,或OrderBy和ThenByDescending。

I'm pretty sure that .OrderBy( m => new { m.CategoryID, m.Name }) and .OrderBy( m => new { m.Name, m.CategoryID }) will produce the same results rather than respecting the intended priority. It will sometimes appear to give you the ordering you want purely by coincidence. Additionally m.CategoryID.ToString() + m.Name will produce incorrect orderings if CategoryID is an int. For example, something with id=123, name=5times will appear after id=1234, name=something instead of before. It's also not inefficient to do string comparisons where int comparisons could occur.

我非常确定.OrderBy(m=>new{m.CategoryID,m.Name})和.OrderBy(m=>new{m.Name,m.CategoryID})将产生相同的结果,而不是尊重预期的优先级。有时,它似乎纯粹是巧合地给出了你想要的顺序。此外,如果CategoryID为int,则m.CategoryID.ToString()+m.Name将产生不正确的排序。例如,id=123,name=5次的内容将出现在id=1234,name=Something之后,而不是之前。在可能发生int比较的情况下进行字符串比较也不是低效的。

When I try to order by on an anonymous type, I get an ArgumentException with the message "At least one object must implement IComparable.". I see others having to declare a comparer when doing this. See stackoverflow.com/questions/10356864/… .

当我尝试对匿名类型进行排序时,我得到一个ArgumentException异常,并显示消息“至少有一个对象必须实现ICompable。”我看到其他人在这样做时必须声明一个比较器。参见Stackoverflow.com/Questions/10356864/…。

This is absolutely wrong. Ordering by a new anonymous type that has no ICompariable implementation cannot work, because there is not order to the properties of an anonymous type. It wouldn't know whether to sort on CategoryID first or Name first, let alone if they were to be sorted in opposite orders.

这是绝对错误的。按没有ICompiable实现的新匿名类型排序不起作用,因为匿名类型的属性没有顺序。它不知道是先按CategoryID排序还是先命名,更不用说按相反的顺序排序了。

This answer is gold! I'll combine the check for queryable.IsOrdered() with the answer from this post, to have a single method that takes a sort direction: stackoverflow.com/questions/388708

这个答案是金子!我将把queryable.IsOrded()的检查与本文的答案结合起来,得到一个采用排序方向的方法:Stackoverflow.com/Questions/388708

This way Linq implementation should go in the first place! OrderBy is badly designed...

这样一来,Linq实现就应该放在首位!OrderBy的设计很糟糕..。

You can easily extend this extension in order to consider nullable values. Refer to: stackoverflow.com/a/36507021

您可以很容易地扩展此扩展以考虑可为空的值。请参阅:Stackoverflow.com/a/36507021

I like this as being more general than thenby since you can do weird things with the compare including having different compare objects with different algorithms ready to go. This is better than my preferred solution before learning about thenby which was to create a class that implements the IComparable interface.

我喜欢这样做,因为它比当时更通用,因为您可以使用比较来做奇怪的事情,包括让不同的比较对象和不同的算法准备就绪。这比我在了解之前的首选解决方案要好,我的首选解决方案是创建一个实现ICompable接口的类。

Since 2012 (.NET version 4.5) you do not have to create a class MovieComparer yourself; instead you can do _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); } }));. Of course, if you prefer to write the logic as one expression, instead of if...else, then the lamda (x, y) => expr can be simpler.

从2012年(.NET版本4.5)开始,您不必自己创建类MovieCompeller;相反,您可以做_db.Movies.OrderBy(Item=>Item,Compeller.Create((x,y)=>{if(x.CategoryId==y.CategoryId){Return x.Name.CompareTo(y.Name);}Else{Return x.CategoryId.CompareTo(y.CategoryId);}}));。当然,如果您更喜欢将逻辑编写为一个表达式,而不是if...Else,那么lamda(x,y)=>expr可能会更简单。

Anonymous expressions will be parsed locally by entity framework core. The LINQ expression could not be translated and will be evaluated locally.

匿名表达式将由实体框架核心在本地进行解析。无法转换LINQ表达式,将在本地计算该表达式。

37 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com