[英]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.