2014-01-31 67 views
1

的数量来选择母行的次序最好的方式,我有我的表注释像以下:的Linq:儿童

Comment{ 
ID, 
Text, 
ParentID 
} 

我使用下面的查询基于回复数字选择分页热门评论。

var comments = db.Comments 
.OrderByDescending(c => db.Comments.Count(r => r.ParentID == c.ID)).Skip(skip).Take(recordsPerPage).ToList(); 

请让我知道处理这种情况的最佳方式,当我们有成千上万的评论?

+1

你有没有考虑增加一个额外的列到'评论'存储回复计数? –

+1

我认为您在订购前跳过并采取措施,可能会给您错误的结果。 – drw85

+0

@ drw8你可能是对的我想。我会看看我的原始代码是否如此。 – user3219798

回答

2

我会考虑增加一个额外的列Comment存储的答复计数。然后,而不是做一个嵌套的查询,你可以轻松地按回复计数您的Comments

var comments = db.Comments.Skip(skip).Take(recordsPerPage) 
       .OrderByDescending(c => c.ReplyCount) 
       .ToList(); 
+0

我已经考虑过添加一个列,但是我必须在每次回复被主持,标记或删除时重新计算ReplyCount ..这又是一种开销,所以我想如果有一种使用linq的最佳方式。 – user3219798

+0

我明白了,但它不应该是一个开销,你只需要更新一个评论回复计数,每次回复是主持,标记或删除..我认为这是合理的比较在你目前的情况 –

+0

我想我会做现在回复计数,除非有人发布更好更简单的方法。 – user3219798

1

除非你准备在数据库中预先计算这点,你有,你需要做的任何嵌套查询或者做一个全取内存中的,然后尽一切问题。后者是我的选择,直到它被证明太慢。

下面是我最初的做法。

首先,预取:

var allComments = Comments.ToArray(); 

然后创建一个可快速返回的评论计数功能:

var childrenLookup = allComments.ToLookup(x => x.ParentID); 
var parentMap = allComments.ToDictionary(x => x.ID, x => x.ParentID); 

Func<int, int> getCommentsCount = n => 
{ 
    var r = 0; 
    if (parentMap.ContainsKey(n)) 
    { 
     r = childrenLookup[parentMap[n]].Count(); 
    } 
    return r; 
}; 

现在它几乎是微不足道的返回结果:

var comments = allComments 
    .OrderByDescending(c => getCommentsCount(c.ID)) 
    .Skip(skip) 
    .Take(recordsPerPage) 
    .ToList(); 

(并且,是的,您的订购顺序错误,您可以跳过并寻求分页。)

如果你不能在内存中执行此操作,请使用预先计算的方法。

+0

感谢您的回答,我想我会预先计算这个项目,但肯定会考虑这种方法。谢谢!! – user3219798