# Get all children recursively in Entity Framework Core

In Entity Framework Core we can have recursive entities. But we cannot do an "Include" for these recursives (can we?). So I wrote a Get-method that does it for me:

First, this is my RecursiveEntity<T> base-class:

public class Entity : IEntity
{
[Key]
public int Id { get; set; }
}

public abstract class RecursiveEntity<TEntity> : Entity, IRecursiveEntity<TEntity>
where TEntity : RecursiveEntity<TEntity>
{
public virtual TEntity Parent { get; set; }
public virtual ICollection<TEntity> Children { get; set; }
}


And this is my Repository-base-class for recurisve entities:

public abstract class RecursiveRepository<T, TDataContext>
where T : RecursiveEntity<T> where TDataContext : DbContext
{
protected IEnumerable<T> Get(Expression<Func<T, bool>> expression)
{
IQueryable<T> parents = DataContext.Set<T>()
.Include(x => x.Children)
.Where(w => w.Parent == null)
.Where(expression);

foreach (T entity in parents)
{
if (entity.Children != null && entity.Children.Any())
entity.Children = _getChildren(entity, expression).ToList();

yield return entity;
}
}

private IEnumerable<T> _getChildren(T parentEntity, Expression<Func<T, bool>> expression)
{
IQueryable<T> children = DataContext.Set<T>()
.Include(x => x.Parent)
.Where(w => w.Parent != null && w.Parent.Id == parentEntity.Id)
.Where(expression);

foreach (T entity in children)
{
entity.Children = _getChildren(entity, expression).ToList();
yield return entity;
}
}
}


Any suggestion what I can do better? Is it a good solution to do that many DataContext<Set>-accesses and assign them to the parent with ToList()?

• Can there be cycles in this recursive entity? For instance, can my parent be my grandchild? – dfhwze Jun 5 '19 at 10:40
• @dfhwze good point! regarding database, yes, it's possible. I should handle that in my backend - no, I dont want circular references. – Matthias Burger Jun 5 '19 at 10:42
• I don't know whether EF supports dynamic hierarchical loading. it didn't in the past. However, one way to try and solve this it is to load the objects as a flattened list and then build the hierarchy in memory. – dfhwze Jun 5 '19 at 10:51

If you remove virtual from Children it'll work with Include(e => e.Children):

  public abstract class RecursiveEntity<TEntity>
: Entity, IRecursiveEntity<TEntity>
where TEntity : RecursiveEntity<TEntity>
{
public virtual TEntity Parent { get; set; }
public ICollection<TEntity> Children { get; set; }
}


The meaning with virtual is to provide lazy loading. If you can't live with that, you'll have to do it manually, as you do.

UPDATE

I seems that EF 6 and EFCore work differently when it comes to Include?

EFCore has the Include() and ThenInclude pattern but that is rather useless for recursive initialization.

public IEnumerable<TEntity> Get<TEntity>(Expression<Func<TEntity, bool>> filter) where TEntity: RecursiveEntity<TEntity>
{
foreach (TEntity entity in Set<TEntity>().Where(e => e.Parent == null).Where(filter))
{
GetChildren(entity, filter);
yield return entity;
}
}

private void GetChildren<TEnity>(TEnity parent, Expression<Func<TEnity, bool>> childFilter) where TEnity : RecursiveEntity<TEnity>
{

if (parent.Children != null)
{
foreach (TEnity child in parent.Children)
{
GetChildren(child, childFilter);
}
}
}


It should produce the same result as yours, but is maybe a little clearer and in line with the EF concept.

• would be nice - I tried, but in my case, it only loads the direct children. not the children of the children.. – Matthias Burger Jun 5 '19 at 12:34
• @MatthiasBurger: Strange it works in EF 6 – Henrik Hansen Jun 5 '19 at 13:44
• I heared that in EF core, the "virtual" is not used anymore like in EF 6. And imho EF Core is not a "follower" of EF 6. Maybe this is not implemented. But I'll test it again later – Matthias Burger Jun 5 '19 at 13:50