EF Core linq and conditional include and theninclude problem
The technique you are using is not really explicit loading (Include
/ ThenInclude
), but trick based on projection and EF Core navigation property fix-up, so I can't say why it stops working. EF Core still processes projections and includes differently, so it might be a defect in the current processing.
Implementing conditional include at the root query level is relatively easy. Note that the Include
method starts from (is defined for) IQueryable<TEntity>
and the returned IIncludableQueryable<TEntity, TPreviousProperty>>
is also IQueryable<TEntity>
. Which means you can keep IQueryable<T>
query variable and apply conditional transformations similar to chained Where
operators.
To make that easier, you could create a custom helper extension method like this:
public static IQueryable<T> If<T>(
this IQueryable<T> source,
bool condition,
Func<IQueryable<T>, IQueryable<T>> transform
)
{
return condition? transform(source) : source;
}
and use it like this:
_context.Investors.Where(s => s.Id == userId)
.If(flagCoins, q => q.Include(e => e.Coins)
.ThenInclude(e => e.CoinType))
.If(flagBricks, q => q.Include(e => e.Bricks))
If you need something similar for the nested levels (ThenInclude
), then add the following 2 extension methods:
public static IQueryable<T> If<T, P>(
this IIncludableQueryable<T, P> source,
bool condition,
Func<IIncludableQueryable<T, P>, IQueryable<T>> transform
)
where T : class
{
return condition ? transform(source) : source;
}
public static IQueryable<T> If<T, P>(
this IIncludableQueryable<T, IEnumerable<P>> source,
bool condition,
Func<IIncludableQueryable<T, IEnumerable<P>>, IQueryable<T>> transform
)
where T : class
{
return condition ? transform(source) : source;
}
which will allow you to use something like this:
_context.Investors.Where(s => s.Id == userId)
.If(flagCoins, q => q.Include(e => e.Coins)
.If(flagCoinType, q2 => q2.ThenInclude(e => e.CoinType)))
.If(flagBricks, q => q.Include(e => e.Bricks))