我想我明白你要做什么 . 让我看看我是否先得到它 .
给定一个选定的 PostID ,您希望返回所有注释,以便在创建顺序中返回顶级注释(即没有父级),并且在每个父级之后和下一个不相关的父注释之前按创建顺序返回所有子注释 . 是对的吗?
我创建了以下类和测试数据:
public class Comment
{
public int CommentId { get; set; }
public int PostId { get; set; }
public int? ParentId { get; set; }
public string Content { get; set; }
}
var comments = new List()
{
new Comment() { PostId = 2, CommentId = 1, },
new Comment() { PostId = 2, CommentId = 2, ParentId = 1, },
new Comment() { PostId = 2, CommentId = 3, },
new Comment() { PostId = 2, CommentId = 4, ParentId = 1, },
new Comment() { PostId = 2, CommentId = 6, ParentId = 5, },
new Comment() { PostId = 2, CommentId = 7, ParentId = 1, },
new Comment() { PostId = 2, CommentId = 8, ParentId = 3, },
// PostId = 3 to test the filter is working
new Comment() { PostId = 3, CommentId = 9, },
// Move this last to test the ordering is working
new Comment() { PostId = 2, CommentId = 5, ParentId = 3, },
};
我假设 CommentId 将自动递增,以便它可用于确定创建顺序 .
因此,如果我了解您的要求,您需要以下输出顺序:
id == 1 [pid == ]
id == 2 [pid == 1]
id == 4 [pid == 1]
id == 7 [pid == 1]
id == 3 [pid == ]
id == 5 [pid == 3]
id == 6 [pid == 5]
id == 8 [pid == 3]
需要执行的查询是:
var postId = 2;
var childCommentsLookup =
(from c in comments
where c.PostId == postId
orderby c.CommentId
select c).ToLookup(x => x.ParentId);
此查询不对注释进行排序,但会强制在数据库中执行单个查询,并返回与 postId 关联的所有注释 .
现在有两种方法可以按正确的顺序获得评论 .
首先,递归的lambda表达式:
//Must declare this as null to allow recursive calling of the lambda.
Action> output = null;
output = (p, l) =>
{
foreach (var c in l[p])
{
Console.WriteLine("id == {0} [pid == {1}]", c.CommentId, c.ParentId);
output(c.CommentId, l);
}
};
output(null, childCommentsLookup);
其次,您可以使用迭代器方法简单地以正确的顺序获取带有注释的 IEnumerable :
public static IEnumerable OrderCommentsRecursively(
int? parent, ILookup lookup)
{
foreach (var c0 in lookup[parent])
{
yield return c0;
foreach (var c1 in OrderCommentsRecursively(c0.CommentId, lookup))
{
yield return c1;
}
}
}
foreach (var c in OrderCommentsRecursively(null, childCommentsLookup))
{
Console.WriteLine("id == {0} [pid == {1}]", c.CommentId, c.ParentId);
}
现在,如果你要创建一个迭代器函数,我会更进一步做一个很好的方法来直接返回你的结果:
public static IEnumerable GetRecursivelyOrderedCommentsByPostId(
IEnumerable comments, int postId)
{
return OrderCommentsRecursively(null,
(from c in comments
where c.PostId == postId
select c).ToLookup(x => x.ParentId));
}
foreach (var c in GetRecursivelyOrderedCommentsByPostId(comments, postId))
{
Console.WriteLine("id == {0} [pid == {1}]", c.CommentId, c.ParentId);
}
这两种/三种方法的结果是:
Lambda Expression:
id == 1 [pid == ]
id == 2 [pid == 1]
id == 4 [pid == 1]
id == 7 [pid == 1]
id == 3 [pid == ]
id == 5 [pid == 3]
id == 6 [pid == 5]
id == 8 [pid == 3]
Iterator Call:
id == 1 [pid == ]
id == 2 [pid == 1]
id == 4 [pid == 1]
id == 7 [pid == 1]
id == 3 [pid == ]
id == 5 [pid == 3]
id == 6 [pid == 5]
id == 8 [pid == 3]
Query & Iterator Call:
id == 1 [pid == ]
id == 2 [pid == 1]
id == 7 [pid == 1]
id == 4 [pid == 1]
id == 3 [pid == ]
id == 5 [pid == 3]
id == 6 [pid == 5]
id == 8 [pid == 3]
我希望这有帮助 .