LinqKit applying nested filtering through extension-method not working

I’m facing a strange behavior using LinqKit with EF Core.

This is my query:

var divisionFilter = new DivisionFilter
{
    VisibilityFilter = (DivisionVisibilityFilter)true
};

await DbContext.Events.Get(new EventFilter
{
    IsVisibleFilter = (EventIsVisibleFilter)true,
    IdIncludeExcludeFilter = (EventIdIncludeExcludeFilter)new IncludeExcludeFilter<Guid> { Includes = new[] { eventId } }
}).Select(e => new
{
    Divisions = e.Divisions
        .Get(divisionFilter) // throws excepetion
        .Where(d2 => divisionFilter.FilterExpression.Expand().Invoke(d2)) // works fine
        .Select(division => new
        {
            division.DivisionId,
            division.DivisionName,
            division.DivisionGender
        })
}).SingleAsync()

Currently I use two extensions to apply the filter’s FilterExpression which is of type Expression<Func<TEntity, bool>>

public static IQueryable<TEntity> Get<TEntity, TEntityFilter>(this DbSet<TEntity> dbSet, TEntityFilter filter)
    where TEntity : BaseEntity<TEntity>, new()
    where TEntityFilter : EntityFilter<TEntity>
{
    return dbSet.AsExpandable().Where(entity => filter.FilterExpression.Invoke(entity));
}

public static IEnumerable<TEntity> Get<TEntity, TEntityFilter>(this IEnumerable<TEntity> entities, TEntityFilter filter)
    where TEntity : BaseEntity<TEntity>, new()
    where TEntityFilter : EntityFilter<TEntity>
{
    return entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}

whereas the first one applies the AsExpandable to the top-table and the second one is used for filtering nested navigation-properties.

However, if using the Get on the nested property it throws the exception

The LINQ expression ‘division’ could not be translated

which is coming from the Select-clause.

If I directly use the Where-clause and adding Expand().Invoke(d2) it work as expected but not when using the extension. In my eyes, both calls are identical but obviously, they are not and I don’t see what the issue is.

Answer

You have to mark your Get method as expandable:

[Expandable(name(GetEnumerable))]
public static IEnumerable<TEntity> Get<TEntity, TEntityFilter>(this IEnumerable<TEntity> entities, TEntityFilter filter)
    where TEntity : BaseEntity<TEntity>, new()
    where TEntityFilter : EntityFilter<TEntity>
{
    return entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}

private static Expression<Func<IEnumerable<TEntity>, TEntityFilter, IEnumerable<TEntity>>> GetEnumerable()
{
    return (entities, filter) => 
        entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}

Leave a Reply

Your email address will not be published. Required fields are marked *