简体   繁体   English

如何递归加载所有子记录?

[英]How can I load all child records recursively?

I have this Project class:我有这个项目 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我得到的错误信息是

The body of 'ProjectsController.LoadDescendantsOf(Project)' cannot be an iterator block because 'Task>' is not an iterator interface type 'ProjectsController.LoadDescendantsOf(Project)' 的主体不能是迭代器块,因为 'Task>' 不是迭代器接口类型

I have tried making the method synchronous, but it's the same error message, only without the "Task"-part.我尝试过使方法同步,但它是相同的错误消息,只是没有“任务”部分。

How can I make it work?我怎样才能让它工作?

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);
                }
            }
        }
    }

And usage:和用法:

var allProjectIds = p.Traverse(x => x.ChildProjects).Select(x => x.Id).ToList();

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:如果要加载子项目,我建议为此在游标上编写递归 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.

相关问题 如何以递归方式在对象子级列表中找到所有对象? - How can I find all of objects in a list of an object's child recursively? 如何递归浏览IIS的所有内容? - How can I recursively browse all content of IIS? 如何递归获取所有非系统目录? - How can I recursively get all non-system directories? 如何使用所有引用递归地将程序集加载到 AppDomain? - How to Load an Assembly to AppDomain with all references recursively? C#/Linq 如何通过 ParentId 然后通过 FolderId 递归获取所有记录 - C#/Linq How to get all records by ParentId and then by FolderId recursively 如何递归地从孩子 c# 中获取所有父母? - How to recursively get all the parents from a child c#? 我可以将Visual Studio设置为卸载所有项目,而不是选择1个项目并仅以递归方式加载其依赖项吗? - Can I set up Visual Studio to unload all projects, than choose 1 project and only load its dependencies recursively? 如何在实体框架 6 中动态加载子实体 - How can I load Child entities dynamically in Entity Framework 6 如何递归返回属性及其所有父项的反映名称 - How can I recursively return the reflected names of a property and all its parents 如何从XML加载子元素列表? - How can I load list of child elements from XML?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM