Entity framework linq query Include() multiple children entities

Viewed 354982

This may be a really elementry question but whats a nice way to include multiple children entities when writing a query that spans THREE levels (or more)?

i.e. I have 4 tables: Company, Employee, Employee_Car and Employee_Country

Company has a 1:m relationship with Employee.

Employee has a 1:m relationship with both Employee_Car and Employee_Country.

If i want to write a query that returns the data from all 4 the tables, I am currently writing:

Company company = context.Companies
                         .Include("Employee.Employee_Car")
                         .Include("Employee.Employee_Country")
                         .FirstOrDefault(c => c.Id == companyID);

There has to be a more elegant way! This is long winded and generates horrendous SQL

I am using EF4 with VS 2010

6 Answers

Might be it will help someone, 4 level and 2 child's on each level

Library.Include(a => a.Library.Select(b => b.Library.Select(c => c.Library)))
            .Include(d=>d.Book.)
            .Include(g => g.Library.Select(h=>g.Book))
            .Include(j => j.Library.Select(k => k.Library.Select(l=>l.Book)))

To doing this:

namespace Application.Test
{
    using Utils.Extensions;
    public class Test
    {
        public DbSet<User> Users { get; set; }
        public DbSet<Room> Rooms { get; set; }
        public DbSet<Post> Posts { get; set; }
        public DbSet<Comment> Comments { get; set; }
        
        public void Foo()
        {
            DB.Users.Include(x => x.Posts, x => x.Rooms, x => x.Members);
            //OR
            DB.Users.Include(x => x.Posts, x => x.Rooms, x => x.Members)
                .ThenInclude(x => x.Posts, y => y.Owner, y => y.Comments);
        }
    }
}

this extension might be helpful:

namespace Utils.Extensions
{
    using Microsoft.EntityFrameworkCore;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Linq.Expressions;
    public static partial class LinqExtension
    {
        public static IQueryable<TEntity> Include<TEntity>(
            this IQueryable<TEntity> sources,
            params Expression<Func<TEntity, object>>[] properties)
            where TEntity : class
        {
            System.Text.RegularExpressions.Regex regex = new(@"^\w+[.]");
            IQueryable<TEntity> _sources = sources;
            foreach (var property in properties)
                _sources = _sources.Include($"{regex.Replace(property.Body.ToString(), "")}");
            return _sources;
        }

        public static IQueryable<TEntity> ThenInclude<TEntity, TProperty>(
            this IQueryable<TEntity> sources,
            Expression<Func<TEntity, IEnumerable<TProperty>>> predicate,
            params Expression<Func<TProperty, object>>[] properties)
            where TEntity : class
        {
            System.Text.RegularExpressions.Regex regex = new(@"^\w+[.]");
            IQueryable<TEntity> _sources = sources;
            foreach (var property in properties)
                _sources = _sources.Include($"{regex.Replace(predicate.Body.ToString(), "")}.{regex.Replace(property.Body.ToString(), "")}");
            return _sources;
        }
    }
}
Related