【问题标题】:Loop recursive self join table循环递归自连接表
【发布时间】:2014-06-16 10:03:24
【问题描述】:

我有如下 SQL Server 表结构,它是一个逻辑树文件夹结构。

我将 Linq to SQL 与 SQL Server 一起使用。

我想要做的是循环并在内存上创建文件夹结构,从根目录到所有子目录的主要父级文件夹结构。

我正在尝试使用一些 foreach 循环来做到这一点,但我仍然不明白。我想我必须使用某种递归方式。

我尝试了一些查询:

var flds = from folders in repo.Folders
                                   join folders2 in repo.Folders on folders.Id equals folders2.idParent
                                   select folders;

我的目标是迭代该文件夹的逻辑结构。

【问题讨论】:

  • Searching a tree using LINQ 的可能重复项
  • @sdrzymala 完全不同的问题。您的链接在 Linq2Object 上。这是Linq2Sql。他们唯一共享的是语法。

标签: c# sql .net sql-server linq


【解决方案1】:

如果您想将文件夹作为表中给定的层次结构,您可以这样创建它:

    var tableData = repo.Folders.ToList();
    var directories = tableData.Select(f => GetPath(f, table));

正如你所问,创建文件夹层次结构的递归方法是:

    private static string GetPath(Folder f)
    {
        if (f.IdParent == 0)
        {
            return f.Name;
        }
        else
        {
            var parent = tableData.Find(d => d.Id == f.IdParent);
            return GetPath(parent) + "|" + f.Name;
        }
    }

你会得到这样的输出:

它会给你一个完整的文件夹层次结构,我不知道你想如何使用它。因此,您可以根据需要进行一些修改。希望对您有所帮助!

这里我添加代码来迭代和创建文件夹结构:

        foreach (var dir in directories)
        {
            var folders = dir.Split('|');
            var path = string.Empty;
            foreach (var folder in folders)
            {
                path = path + "\\" + folder;  // modify the path like '\\' if it is not valid I have not tested
                CreateFolder(path); // implement this method for actual creation of folders
            }
        }

还有你创建文件夹的方法:

private static void CreateFolder(string directory)
    {
        var path = "C:" + directory; // add whenever you want to create structure
        if (!Directory.Exists(path))
        {
            Directory.CreateDirectory(path);
        }
    }

【讨论】:

  • 目前,我只想在控制台中打印文件夹树。 “表”参数是什么?对不起,如果菜鸟问题
  • 我用过 LINQ to Objects,所以从你的表中选择了文件夹列表,然后按上面的方法处理它。所以表只是表中的原始文件夹列表
  • 如果表在你的类中是全局的,那么不需要在递归方法中传递它,我只是在控制台程序中工作,所以我添加了。
  • Mak,它不适用于我的项目,当我尝试迭代文件夹“var 文件夹”时,它给了我一个空指针。有什么建议吗?
  • 我不知道你想如何使用它,所以请告诉我你想如何迭代并使用它。
【解决方案2】:

你可以试试这个:

// Get a list of the folders.
// We do this, in order to avoid the performance hit, that Panagiotis 
// pointed out correctly in his comment.
var folders = repo.Folders.ToList();

// Get the root folder.
var rootFolder = folders.Where(x=>x.idParent==null).SingleOrDefault();

// Group the folders by their parentId.
var groupedFolders = from folder in folders
                     where folder.idParent!=null
                     orderby folder.idParent ascending
                     group folder by folder.idParent into grp
                     select new
                     {
                         ParentFolderId = grp.Key,
                         Folders = grp.Select(x=>x)
                     };

// Print the name of the root folder.
Console.WriteLine("Root Folder", rootFolder.Name);

// Iterate through the groups of folders. 
foreach(var grp in groupedFolders)
{
    // Get the name of the parent folder for the current group.
    string parentFolderName = folders.Where(x=>x.Id==grp.ParentFolderId)
                                     .Single(x=>x.Name);


    // Print the name of the parent folder.
    Console.WriteLine("Parent Folder", parentFolderName);

    // Iterate through the folders of the current group.
    foreach(var folder in grp.Folders)
    {
        Console.WriteLine(folder.Name);
    }
}

【讨论】:

  • 如果 repo 是一个 DataContext 这将导致糟糕的性能,因为它会导致每个文件夹命中一个数据库。如果 OP 已经在内存中有结果,则没有理由这样做。
  • 感谢您指出这一点!老实说,我没有注意表演。我会更正我的帖子。
  • 您的回答似乎只是检索第一级文件夹/条目。
猜你喜欢
  • 2018-09-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
  • 2021-08-09
  • 2018-06-27
  • 2017-01-21
相关资源
最近更新 更多