LINQ to Entities关于orderby和null集合的问题

时间:2011-01-09 05:01:57

标签: c# linq entity-framework linq-to-entities

我目前正在开发一个论坛。我是LINQ和EF的新手。在我的论坛中,我有一个显示首先显示最新主题的主题列表。

问题是"最近"与主题的回复有关。因此,我不想按主题的发布日期订购列表,而是希望按主题的最后回复的发布日期订购列表。因此,具有较新回复的主题会弹回到列表顶部。如果我知道每个主题都至少有一个回复,那就相当简单了;我会这样做:

var topicsQuery = from x in board.Topics
                  orderby x.Replies.Last().PostedDate descending
                  select x;

但是,在许多情况下,该主题没有回复。在这种情况下,我想使用主题的发布日期。如果主题没有回复,我的linq查询中有没有办法按x.PostedDate排序?我对此感到困惑,任何帮助都会受到赞赏。通过上面的查询,由于假定有回复的x.Replies.Last(),它会在没有回复的主题上中断。 LastOrDefault()无效,因为我需要访问PostedDate属性,该属性也假设存在回复。

提前感谢任何见解。

4 个答案:

答案 0 :(得分:7)

var topicsQuery = from x in board.Topics
                  let lastActivityDate = x.Replies.Any() 
                         ? x.Replies.Last().PostedDate 
                         : x.PostedDate
                  orderby lastActivityDate descending
                  select x;

修改

要回答您的评论,linq表达式语法没有“让”显式。但是,您可以实现以下相同(使用中间选择表达式):

var topicsQuery = board.Topics.Select(x => new { 
                                                  Topic = x, 
                                                  LastActivityDate = x.Replies.Any() 
                                                      ? x.Replies.Last().PostedDate 
                                                      : x.PostedDate
                                    })
                             .OrderByDescending(p => p.LastActivityDate)
                             .Select(r => r.Topic)

<强> EDIT2:

这可以进一步简化,正如尼古拉斯建议的那样,我们也可以删除中间选择语句。注意,如果没有不同的执行,这是不可能的。

var topicsQuery = board.Topics
        .OrderByDescending(x => x.Replies.Any() 
                                      ? x.Replies.Last().PostedDate 
                                      : x.PostedDate);

答案 1 :(得分:2)

我无法发表评论。 FWIW,将其视为评论。

var topicsQuery = from x in board.Topics
              let lastActivityDate = x.Replies.Any() 
                     ? x.Replies.Last().PostedDate 
                     : x.PostedDate
              orderby lastActivityDate descending
              select x;

您可能想要更改

x.Replies.Last().PostedDate 

这个

x.Replies.OrderByDesc( r => r.PostedDate).First().PostedDate

答案 2 :(得分:0)

您是否考虑过为主题数据添加新字段?像LastActivityDate之类的东西。最初将其设置为主题PostedDate,然后在每次添加回复时更新。

我不是SQL Server专家,但是如果您尝试使用查询执行的操作,您可能最终会得到一个忽略索引并执行全表扫描的查询。

答案 3 :(得分:0)

典型的论坛有很多读取和少量写入,特别是在这种特殊情况下。因此,我会选择将LastPostDate缓存在一个额外的字段中。它提供了一些冗余和更多的编程来保持最新值,但我认为在大多数情况下它是最好的方式。