Фильтр IQueryable с общим лямбда-выражением

Я пытаюсь отфильтровать поля DateTime? моих классов с помощью общей функции. Но у меня ошибка "The LINQ expression could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync()."

И я не знаю, что не так.

Это моя функция расширения:

public static IQueryable<TEntity>? FilterDateField<TEntity>(this IQueryable<TEntity> entities, Expression<Func<TEntity, DateTime?>> dbField, DateTime dateField)
{
    var t1 = entities.Where(e=>dbField.Compile().Invoke(e).HasValue && dbField.Compile().Invoke(e)== dateField);

    return t1;
}

person Lucas Gabriel    schedule 17.09.2020    source источник
comment
Можете ли вы предоставить более подробную информацию? Пример данных, которые вы пытаетесь отфильтровать?   -  person Stefan Jovanchevski    schedule 17.09.2020


Ответы (1)


Я получаю ответ на другой вопрос здесь: Общий метод фильтрации Linq to Entities, который принимает критерии фильтрации и свойства для фильтрации

Просто добавьте этот код в класс, который содержит функцию FilterDateField

public static Expression<Func<TFirstParam, TResult>>  Compose<TFirstParam, TIntermediate, TResult>(
    this Expression<Func<TFirstParam, TIntermediate>> first, Expression<Func<TIntermediate, TResult>> second)
{
    var param = Expression.Parameter(typeof(TFirstParam), "param");

    var newFirst = first.Body.Replace(first.Parameters[0], param);
    var newSecond = second.Body.Replace(second.Parameters[0], newFirst);

    return Expression.Lambda<Func<TFirstParam, TResult>>(newSecond, param);
}

public static Expression Replace(this Expression expression, Expression searchEx, Expression replaceEx)
{
    return new ReplaceVisitor(searchEx, replaceEx).Visit(expression);
}
internal class ReplaceVisitor : ExpressionVisitor
{
    private readonly Expression from, to;
    public ReplaceVisitor(Expression from, Expression to)
    {
        this.from = from;
        this.to = to;
    }
    public override Expression Visit(Expression node)
    {
        return node == from ? to : base.Visit(node);
    }
}

И они используют de Compose следующим образом:

public static IQueryable<TEntity>? FilterDateField<TEntity>(this IQueryable<TEntity> entities, Expression<Func<TEntity, DateTime?>> dbField, DateTime dateField)
{
    var dateHasValue = dbField.Compose(value => value.HasValue);
    var t1 = entities.Where(dateHasValue);

    return t1;
}
person Lucas Gabriel    schedule 17.09.2020