1

I have an object:

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

and I've written a query that retrieves a folder structure and all files within each folder:

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

The above returns exactly what I need, but I don't like the code, cause it causes problems if I would like to add multiple more layers to the folder structure.

Any ideas how I could write this, so I get all Child folders, and all files despite the number of layers I have in my folder structure?

4
  • 2
    Why not use a good old recursive tree traversal? Commented May 6, 2014 at 8:55
  • 1
    Have a look at this: stackoverflow.com/questions/61143/… Commented May 6, 2014 at 8:58
  • 1
    Can you clarify: Are you using a DB and you want this to be translated to one DB command? Commented May 6, 2014 at 9:02
  • I am using a db and this is the basic query I'm after SELECT * FROM Folders f LEFT JOIN FileEntries fe On f.Id = fe.Folder_Id Commented May 6, 2014 at 9:14

2 Answers 2

1

Sadly there is no recursive support in LINQ AFAIK (I faced the same problem), but you at least can shorten it to:

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

All "lower levels" are also included if you select the "higher level".

I THINK this is because SQL also has no support for this...

If you are fine with executing this "in code" using multiple queries to the DB (or you not using a DB at all) see golergka's comment.

Sign up to request clarification or add additional context in comments.

Comments

0

You have a tree of folders, and you'd like to look for all files recursively. This can be done using algorithms like depth-first search:

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

This isn't very pretty in C# since it has no support for yielding multiple results, but it works. Also, if you have huge quantities of files, or very nested folders, you might want to implement this algorithm using more efficient techniques (e.g. with a Queue).

1 Comment

Suspecting by DBObjectBase he is using a DB backend so he wants to do this not via code...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.