3

I have the following SQL Server table structure, it's a logical tree folder structure.

SQL Server Table Structure

I'm using Linq to SQL with SQL Server.

What I want to do is to loop and create on memory the folder structure, the hierarchical folder from Root, the main parent to all childs.

Folder structure

I'm trying to do it with some foreach loops but I still don't get it. I think I must use some kind of recursive way.

Some query I tried:

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

My goal is to iterate that folder logical structure.

mehdi lotfi
  • 11,194
  • 18
  • 82
  • 128
alxsimo
  • 567
  • 1
  • 6
  • 19
  • possible duplicate of [Searching a tree using LINQ](http://stackoverflow.com/questions/7062882/searching-a-tree-using-linq) – sdrzymala Jun 16 '14 at 10:21
  • 1
    @sdrzymala completely different question. Your link is on Linq2Object. This is Linq2Sql. The only thing they share is syntax. – Aron Jun 16 '14 at 11:11

2 Answers2

2

If you want to get folder as hierarchy given in your table, you can create it like this :

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

And as you asked, the recursive method for creating a folder hierarchy is :

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

You will get output like this :

Output

It will give you a complete folder hirarchy, I don't know how you want to use it. So you can do some modification as per your need. Hope it helps!

Here I am adding the code to iterate and create the folder structure :

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

And your method for creating 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);
        }
    }
Mukesh Modhvadiya
  • 2,178
  • 2
  • 27
  • 32
  • For the moment, i just want to print the folder tree in the console. What is the "table" parameter is? Sorry if noob question – alxsimo Jun 16 '14 at 11:17
  • I have used LINQ to Objects, so have selected folderlist from your table and then processed it as above. So table is nothing but List of Folder raw in your table – Mukesh Modhvadiya Jun 16 '14 at 11:19
  • If table is as global in your class, then no need to pass it in recursive method, I was just working in console program so I added. – Mukesh Modhvadiya Jun 16 '14 at 11:25
  • Mak, it doesn't work for my project, when i try to iterate the folders "var folders" it gives me a null pointer. Any tips? – alxsimo Jun 16 '14 at 13:56
  • I dont know how you want to use it, so please tell me how you want to iterate and do with that. – Mukesh Modhvadiya Jun 16 '14 at 14:18
  • I just want to create that structure on the phisical disk. The data is obtained from SQL Server via LinqToSQL with a dataContext. Here's the example http://pastebin.com/B5Spnnh9 – alxsimo Jun 16 '14 at 14:34
  • I cannot visit your link, it is blocked here, but I am updating the answer as per your need, wait a little – Mukesh Modhvadiya Jun 16 '14 at 14:37
  • I have updated the answer, with how to create directory structure. You may need some modifications. Kindly look it and accept it if it helps. – Mukesh Modhvadiya Jun 16 '14 at 15:05
  • Mmm.. the problem it hasn't been solved. How you access "tableData" from GetPath if you dont pass it as a parameter? Thanks! – alxsimo Jun 29 '14 at 17:55
  • By the way, i tried this method and fails due a stackoverflow exception. – alxsimo Jun 29 '14 at 19:43
  • I think your question was how to query that table for output, that was answered and your problem was solved. Now this was different question, and you should ask it as new question, so it would become helpful for other people too. You should not ask all your functional problems in one question. – Mukesh Modhvadiya Jun 30 '14 at 05:47
  • By the way, if you could take tableData as global variable then not need to pass, and where you are getting exception?? – Mukesh Modhvadiya Jun 30 '14 at 05:48
  • Mak, my goal wasn't resolved, that's why i don't ask a new question. I want to make this: 1. Get all roots folders (there are more than one) 2. Get the childs of the roots folders 3. Check if the childs obtained in the 2. have sub-childs and get the sub-childs. 4. Now check if the sub-childs in the 3. also have childs too. I want to repeat that actions iterativelly as the childs have no more sub-childs. – alxsimo Jun 30 '14 at 10:45
  • In your question you have asked how to get the nested hirarchy of folders, I have shown you how to recursively call and make the folder hierarchy, you have accepted the answer I think. When there is another problem asking different problems in different questions would helps others too. Well what problem are you facing in above code. – Mukesh Modhvadiya Jun 30 '14 at 12:12
  • Sorry @Mak, i will make a new question. Thank you very very much! – alxsimo Jun 30 '14 at 20:38
  • Thank you for understanding, and not taking things offensive. :) – Mukesh Modhvadiya Jul 01 '14 at 07:02
1

You could try this one:

// 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);
    }
}
Christos
  • 53,228
  • 8
  • 76
  • 108
  • If `repo` is a DataContext this will result in awful performance because it will result in one database hit per folder. There's no reason to do this if the OP already has the results in memory. – Panagiotis Kanavos Jun 16 '14 at 10:34
  • Thank you, for pointing this out! To be honest with you I did't pay attention on the performance. I will correct my post. – Christos Jun 16 '14 at 10:37
  • Your answer it seems only to retrieve the first level of folders/entries. – alxsimo Jun 29 '14 at 18:03