How to implement ThenInclude into EF Core custom specification?

c# entity-framework-core

Question

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?

1
1
2/19/2020 8:28:34 PM

Accepted Answer

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));
2
2/19/2020 10:29:52 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow