如何递归加载所有子记录? [英] How can I load all child records recursively?
问题描述
我有这个Project课程:
I have this Project class:
public class Project
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Project> ChildProjects { get; set; }
// more properties
}
这是我加载任何给定项目的所有后代的尝试:
This is my attempt to load all descendants of any given project:
private async Task<List<Project>> LoadDescendantsOf(Project project)
{
project.ChildProjects = await db.Projects
.Where(p => p.ParentId == project.Id)
.ToListAsync();
foreach (Project childProject in project.ChildProjects)
{
yield return childProject.ChildProjects =
await LoadDescendantsOf(childProject);
}
}
...但是它不起作用.我收到的错误消息是
... but it's not working. The error message I get is
'ProjectsController.LoadDescendantsOf(Project)'的主体不能是迭代器块,因为'Task>'不是迭代器接口类型
The body of 'ProjectsController.LoadDescendantsOf(Project)' cannot be an iterator block because 'Task>' is not an iterator interface type
我尝试使该方法同步,但是它是相同的错误消息,只是没有任务"部分.
I have tried making the method synchronous, but it's the same error message, only without the "Task"-part.
我如何使它工作?
推荐答案
您可以为此编写简单的扩展名:
You can write simple extension for this:
public static IEnumerable<T> Traverse<T>(this T e, Func<T, IEnumerable<T>> childrenProvider)
{
return TraverseMany(new[] { e }, childrenProvider);
}
public static IEnumerable<T> TraverseMany<T>(this IEnumerable<T> collection, Func<T, IEnumerable<T>> childrenProvider)
{
var stack = new Stack<T>();
foreach(var c in collection)
{
stack.Push(c);
}
while (stack.Count > 0)
{
var i = stack.Pop();
yield return i;
var children = childrenProvider(i);
if (children != null)
{
foreach (var c in children)
{
stack.Push(c);
}
}
}
}
和用法:
var allProjectIds = p.Traverse(x => x.ChildProjects).Select(x => x.Id).ToList();
如果您要加载子项目,我建议为此在游标上编写递归SQL过程,但这也适用于小数据:
If you want to load subprojects I would recommend write recursive SQL procedure on cursors for this, but this will also do nice on small data:
var allProjectIds = p
.Traverse(x =>
{
x.ChildProjects = db.Projects
.Where(p => p.ParentId == project.Id)
.ToList();
return x.ChildProjects;
})
.Select(x => x.Id)
.ToList();
这篇关于如何递归加载所有子记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!