我有一个名为Groups的表。该表的结构是:
GroupID 1-------
GroupName |
ParentID *-------
现在我想为特定的父母找到所有的孩子和孙子。
我尝试过以下代码。但它只给了我一到二级的孩子:
List<string> groups = new List<string>();
var parent = (from g in db.Groups
where g.GroupID == 1
select g).FirstOrDefault();
var Children = (from x in db.Groups
where x.ParentID == parent.GroupID
select x);
groups.AddRange(Children.Select(x => x.GroupName));
foreach (Group children in Children)
{
var grandChildren = (from x in db.Groups
where x.ParentID == children.GroupID
select x.GroupName);
groups.AddRange(grandChildren);
}
StringBuilder builder = new StringBuilder();
foreach (string str in groups)
{
builder.Append(str.ToString()).AppendLine();
}
MessageBox.Show(builder.ToString());
答案 0 :(得分:3)
您可以尝试递归地执行此操作:
IEnumerable<Group> GetAllChildren(Group parent)
{
var result = (from x in db.Groups
where x.ParentID == parent.GroupID
select x);
foreach (Group child in result)
{
result.AddRange(GetAllChildren(child));
}
return res;
}
这只是一个例子,并没有检查循环引用。
答案 1 :(得分:1)
如果你不想do it in the database,这可能会更有效率,你可以做这样的事情。
注意,我创建了一个字典,以防止每一代都访问数据库。如果您只获得所有组的一小部分,或者如果代数很小,这可能是错误的方法。
如果重复此过程并且可以缓存组字典,则这将是有效的并且可以防止多次访问数据库。这个函数没有分配额外的内存来构建结果集,只是懒得走树。
IDictionary<int, Group> groups;
using(var db = new Context())
{
groups = db.Groups.ToDictionary(g => g.GroupID, g => g)
}
var all = FlattenGroups(groups, new[] { groups[1] });
private IEnumerable<Group> FlattenGroups(
IDictionary<int, Group> groups,
IEnumerable<group> topSet)
{
return topSet.SelectMany(group =>
FlattenGroups(
groups,
groups[group.ParentID])
.Concat(topSet));
}