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.
You have to mark your Get
method as expandable:
[Expandable(nameof(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>>> GetEnumerablet<TEntity, TEntityFilter>()
{
return (entities, filter) =>
entities.Where(e => filter.FilterExpression.Expand().Invoke(e));
}