简体   繁体   English

在LINQ谓词中使用OrderBy?

[英]Use OrderBy in a LINQ predicate?

In my code I need to sort a collection either by Price or by Rating.TotalGrade and as you can see both LINQ querys are almost the same statement with only a minor difference. 在我的代码中,我需要按PriceRating.TotalGrade对集合进行排序,并且如您所见,这两个LINQ查询几乎是同一条语句,只有很小的不同。

I was thinking about using a LINQ predicate instead but as you can see the the orderby is the main difference and I found no sample using orderby in a query. 我当时在考虑使用LINQ谓词,但是正如您所看到的, orderby是主要区别,在查询中没有发现使用orderby的示例。 Is it possible or are there other ways to shorten my code, Maybe there will be even more conditions in the future. 是否有可能或有其他方法来缩短我的代码,也许将来还会有更多情况。

if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Position)
{
    this.collectionCompleteSorted = new List<Result>(from co in collection
                                    where co.IsVirtual == false
                                    orderby co.Price, co.CurrentRanking
                                    select co);
}
else if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Grade)
{
    this.collectionCompleteSorted = new List<Result>(from co in collection
                                    where co.IsVirtual == false
                                    orderby co.Rating.TotalGrade, co.CurrentRanking
                                    select co);
}

You can easily make use of deffered nature of LINQ and ability to easily compose queries. 您可以轻松利用LINQ的固有特性以及轻松编写查询的功能。

Probably using code like this: 可能使用如下代码:

        var baseQuery = from co in collection where !co.IsVirtual select co; // base of query
        IOrderedEnumerable<Result> orderedQuery; // result of first ordering, must be of this type, so we are able to call ThenBy

        switch(CurrentDisplayMode) // use enum here
        { // primary ordering based on enum
            case CRSChartRankingGraphDisplayMode.Position: orderedQuery = baseQuery.OrderBy(co => co.Price);
                break;
            case CRSChartRankingGraphDisplayMode.Grade: orderedQuery = baseQuery.OrderBy(co => co.TotalGrade);
                break;
        }

        this.collectionCompleteSorted = orderedQuery.ThenBy(co => co.CurrentRanking).ToList(); // secondary ordering and conversion to list

Its easy to understand and avoids converting to list until the very end. 它易于理解,并且避免了直到最后才转换为列表。

If just your order by is different, than return your result into this.collectionCompleteSorted, and then do this.collectionCompleteSorted.OrderBy() when you enumerate through the data. 如果只是您的订单不同,则将结果返回到this.collectionCompleteSorted,然后在枚举数据时执行this.collectionCompleteSorted.OrderBy()。

this.collectionCompleteSorted = new List<Result>(from co in collection 
                                                             where co.IsVirtual == false                                                                  
                                                             select co);

foreach (var obj in this.collectionCompleteSorted.OrderBy(c => c.Price).ToList())
{
    // do something
}

And remove the order by remove your current linq query. 并通过删除当前的linq查询来删除订单。

If the query is just being executed once, than you can leave off the .ToList() from the linq query in the example above. 如果查询仅执行一次,则可以在上面的示例中从linq查询中删除.ToList()。 When ToList is called, this causes the query to be executed immediately, where if the OrderBy is implemented in a later call to the collection and a ToList is also, than the query would actually be executed on the database server with an order by statement, offloading the ordering from the code to the database. 调用ToList时,这将导致查询立即执行,如果在稍后对集合的调用中实现了OrderBy并且也使用了ToList,则查询实际上将在数据库服务器上使用order by语句执行,将订单从代码转移到数据库。 See http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx 参见http://blogs.msdn.com/b/charlie/archive/2007/12/09/deferred-execution.aspx

Why not just grab the values (less the sort), then (as it appears) use a case to order the results? 为什么不只是获取值(减少排序),然后(如出现的那样)使用案例来对结果进行排序?

// build your collection first
var items = from co in collection
            where !co.IsVirtual
            select co;

// go through your sort selectors
select (CurrentDisplayMode)
{
  case CRSChartRankingGraphDisplayMode.Position:
    this.collectionCompleteSorted = items.OrderBy(i => i.Price).ThenBy(j => j.CurrentRanking).ToList();
    break;
  case CRSChartRankingGraphDisplayMode.Grade:
    this.collectionCompleteSorted = items.OrderBy(i => i.TotalGrade).ThenBy(j => j.CurrentRanking).ToList();
    break;
  ...
  //default: // maybe you want this, too
}
var q = collection.Where(co => !co.IsVirtual);

if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Position)
{
    q = q.OrderBy(co => co.Price).ThenBy(co => co.CurrentRanking);
}
else if (CurrentDisplayMode == CRSChartRankingGraphDisplayMode.Grade)
{
    q = q.OrderBy(co => co.Rating.TotalGrade).ThenBy(co => co.CurrentRanking);
}

this.collectionCompleteSorted = q.ToList();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM