Entity Framework Core: load full hierarchy

1.4k views Asked by At

Having a self referencing table, with a ParentId attribute which holds the id of the parent record, what can I do so that using ef I will load into each parent its children.

What I want is to transform this cte which will return the full hierarchy as a collection.

var queryString = @"
        ;WITH cte AS (
            SELECT * FROM [dbo].[Folders] _f WHERE _f.[Id] = @id

            UNION ALL

            SELECT _c.* FROM [dbo].[Folders] _c
            INNER JOIN cte _cte
            ON _cte.[Id] = _c.[ParentFolderId]
        )

        SELECT * FROM cte";


return await this.Entities.FromSql(new RawSqlString(queryString), new SqlParameter("id", id)).ToListAsync();

into something that will somehow load the hierarchy of children into their parents, keeping at the same time the performance of one trip to db.

class Folder
{ 
     public int Id { get; set; }
     public int? FolderId { get; set; }
     public Folder Folder { get; set; }
     public IEnumerable<Folder> Children { get; set; }
}

Hierarchy example

- Main (Id: 1 / ParentId: null) 
     - C1 (2/1) 
           - C11 (4/2) 
                  - C111 (7/4)
           - C12 (5/2)
     - C2 (3/1) 
           - C21 (6/3) 
                  - C211 (8/6)

Configured relation

builder.Ignore(prop => prop.Folder);
builder.HasOne(prop => prop.Folder).WithMany(prop => prop.Children).HasForeignKey(fk => fk.FolderId);
2

There are 2 answers

1
David Browne - Microsoft On

If you want the entire hierarchy in one query, that's easy. Just retrieve all the Folders and if Change Tracking is enabled EF will fix-up all the relationships. IE if you just run

var folders = db.Set<Folder>().ToList();

You'll have the whole hierarcy with all the Navigation Properties populated.

0
Tohid On

You can get the whole hierarchy with this query:

var hierarchy = db.Set<Folder>().Include(f => f.Children).ToList();