【问题标题】:How to write recursive lambda expression (LINQ query)如何编写递归 lambda 表达式(LINQ 查询)
【发布时间】:2014-06-22 19:03:21
【问题描述】:

我有一个对象:

public class Folder : DBObjectBase
{
    public string Name { get; set; }
    public List<FileEntry> Files { get; set; }
    public Folder ParentFolder { get; set; }
    public List<Folder> ChildFolders { get; set; }
}

我已经编写了一个查询来检索文件夹结构和每个文件夹中的所有文件:

var results = DbContext.Set<Folder>()
            .Include(f => f.ParentFolder)
            .Include(f => f.ChildFolders)
            .Include(f => f.Files)
            .Include(f => f.ChildFolders.Select(f1 => f1.Files))
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.Files))
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.ChildFolders.Select(f3 => f3.Files)))
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.ChildFolders.Select(f3 => f3.ChildFolders.Select(f4 => f4.Files))))
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.ChildFolders.Select(f3 => f3.ChildFolders.Select(f4 => f4.ChildFolders.Select(f5 => f5.Files)))))
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.ChildFolders.Select(f3 => f3.ChildFolders.Select(f4 => f4.ChildFolders.Select(f5 => f5.ChildFolders.Select(f6 => f6.Files))))))
            .Where(f => f.ParentFolder == null);

上面返回的正是我需要的,但我不喜欢代码,如果我想在文件夹结构中添加多个层,它会导致问题。

有什么想法可以写这个,所以我得到所有子文件夹,以及所有文件,尽管我的文件夹结构中有多少层?

【问题讨论】:

  • 为什么不使用好的旧递归树遍历?
  • 您能否澄清一下:您使用的是数据库并且希望将其转换为一个数据库命令?
  • 我正在使用数据库,这是我在 SELECT * FROM Folders f LEFT JOIN FileEntries fe On f.Id = fe.Folder_Id 之后的基本查询

标签: c# linq recursion lambda


【解决方案1】:

遗憾的是,LINQ AFAIK 中没有递归支持(我遇到了同样的问题),但您至少可以将其缩短为:

var results = DbContext.Set<Folder>()
            .Include(f => f.ParentFolder)
            .Include(f => f.Files)
            .Include(f => f.ChildFolders.Select(f1 => f1.ChildFolders).Select(f2 => f.ChildFolders.Select(f3 => f3.ChildFolders.Select(f4 => f4.ChildFolders.Select(f5 => f5.ChildFolders.Select(f6 => f6.Files))))))
            .Where(f.ParentFolder == null);

如果您选择“较高级别”,则还包括所有“较低级别”。

我认为这是因为 SQL 也不支持这个...

如果您可以使用对 DB 的多个查询执行此“代码中”(或者您根本不使用 DB),请参阅 golergka 的评论。

【讨论】:

    【解决方案2】:

    您有一个文件夹树,并且您希望递归查找所有文件。这可以使用深度优先搜索等算法来完成:

    public static IEnumerable<FileEntry> GetAllFiles(Folder folder)
    {
        foreach(var file in folder.Files)
        {
            yield return file;
        }
        foreach(var nestedFolder in folder.ChildFolders)
        {
            foreach(var file in GetAllFiles(nestedFolder))
            {
                yield return file;
            }
        }
    }
    

    这在 C# 中不是很漂亮,因为它不支持产生多个结果,但它可以工作。此外,如果您有大量文件或非常嵌套的文件夹,您可能希望使用更有效的技术(例如使用Queue)来实现此算法。

    【讨论】:

    • DBObjectBase 怀疑他正在使用数据库后端,所以他不想通过代码来执行此操作...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-26
    相关资源
    最近更新 更多