[英]How can I load all child records recursively?
我有这个项目 class:
public class Project
{
public int Id { get; set; }
public int? ParentId { get; set; }
public List<Project> ChildProjects { get; set; }
// more properties
}
这是我尝试加载任何给定项目的所有后代:
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);
}
}
...但它不起作用。 我得到的错误信息是
'ProjectsController.LoadDescendantsOf(Project)' 的主体不能是迭代器块,因为 'Task>' 不是迭代器接口类型
我尝试过使方法同步,但它是相同的错误消息,只是没有“任务”部分。
我怎样才能让它工作?
您可以为此编写简单的扩展:
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 过程,但这对小数据也有好处:
var allProjectIds = p
.Traverse(x =>
{
x.ChildProjects = db.Projects
.Where(p => p.ParentId == project.Id)
.ToList();
return x.ChildProjects;
})
.Select(x => x.Id)
.ToList();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.