Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement ThenInclude into EF Core custom specification?

EF Core 3.1 I have seen Specification example, and want to implement ThenInclude pattern.

public static class QuerySpecificationExtensions
{
    public static IQueryable<T> Specify<T>(this IQueryable<T> query, ISpecification<T> spec) where T : class
    {
        // fetch a Queryable that includes all expression-based includes
        var queryableResultWithIncludes = spec.Includes
            .Aggregate(query,
                (current, include) => current.Include(include));

        // modify the IQueryable to include any string-based include statements
        var secondaryResult = spec.IncludeStrings
            .Aggregate(queryableResultWithIncludes,
                (current, include) => current.Include(include));

        // return the result of the query using the specification's criteria expression
        return secondaryResult.Where(spec.Criteria);
    }
}

I can add this into string for example "User.UserRole.Role", but I want to implement object. Maybe there it is not possible?

like image 751
hdoitc Avatar asked Mar 07 '26 07:03

hdoitc


1 Answers

Includes member of the aforementioned ISpecification<T> is declared as

List<Expression<Func<T, object>>> Includes { get; }

The problem is that EF Core Include / ThenInclude chain cannot be represented with Expression<Func<T, object>>. This pattern was used in EF6 which supported a special syntax (Select) inside the include expression to resolve collection element. But EF Core does not support that out of the box.

The easiest and most natural way to plug EF Core pattern is to change the definition as follows:

List<Func<IQueryable<T>, IIncludableQueryable<T, object>>> Includes { get; }

Adding the sample for entity having User property having UserRoles collection having Role property would be like this:

Includes.Add(q => q.Include(e => e.User).ThenInclude(e => e.UserRoles).ThenInclude(e => e.Role));

And the corresponding part of the Specify method implementation would be:

var queryableResultWithIncludes = spec.Includes
    .Aggregate(query,
        (current, include) => include(current));
like image 61
Ivan Stoev Avatar answered Mar 09 '26 23:03

Ivan Stoev