1

I have an object that defines a network structure, I want to send over all children of that object and the children of the children and so on.

Right now I have this:

var Data = await _context.Scans
                .Include(c => c.networkDevices)
                .ThenInclude(d => d.ports)
                .ThenInclude(p => p.Service)
                .Include(c => c.root)
                .ThenInclude(d => d.children).ThenInclude(p => p.children).ThenInclude(c => c.children)
                .ToListAsync();
            return Data;

This code will get most levels but if a network has many different layers it won't get all of them. How can i make it so that all layers get included.

Dutch
  • 23
  • 10
  • 1
    Please look for other questions on Entity Framework + LINQ + hierarchy. This is a continually recurring topic. – Gert Arnold Nov 23 '20 at 13:38
  • Yeah, w/o filter just just use the code as is (and even remove everything starting with `.Include(c => c.root)` - see the linked post marked as "duplicate" ) – Ivan Stoev Nov 23 '20 at 13:44

2 Answers2

1

I think there is no built in way to load "all" layers because in theory it'd be possible that you have cyclic references.

This snippet will create a query for the number of layers

namespace System.Data.Entity
{
  using Linq;
  using Linq.Expressions;
  using Text;

  public static class QueryableExtensions
  {
    public static IQueryable<TEntity> Include<TEntity>(this IQueryable<TEntity> source,
      int levelIndex, Expression<Func<TEntity, TEntity>> expression)
    {
      if (levelIndex < 0)
        throw new ArgumentOutOfRangeException(nameof(levelIndex));
      var member = (MemberExpression)expression.Body;
      var property = member.Member.Name;
      var sb = new StringBuilder();
      for (int i = 0; i < levelIndex; i++)
      {
        if (i > 0)
          sb.Append(Type.Delimiter);
        sb.Append(property);
      }
      return source.Include(sb.ToString());
    }
  }
}

Usage:

var children = await DbContext.Roots
  .Include(3, a => a.Children)
  .SingleOrDefaultAsync(a => a.Id == 5);
Dominik
  • 1,623
  • 11
  • 27
0

I think the easiest way to accomplish this is by lazy loading, take a look at this post

  • This is indeed the simplest - but you must take into account that every time he navigates to the "next child" EF will do a roundtrip to the db. – Dominik Nov 23 '20 at 13:42