Мне нужно повторно использовать доступное выражение:

Expression<Func<Picture, int>> selector = o => o.EntityId;

И построить выражение для Где:

Expression<Func<Picture, bool>> filter = w => w.EntityId > 5;

Как я могу построить такое выражение?

Следующая операция не будет выполнена на стороне клиента, я прав?

var collection = _dbContext.Pictures.Where(filter).ToList();
1
Pavel 24 Апр 2020 в 18:44

2 ответа

Лучший ответ

Я наконец-то понял, как построить выражение динамически:

Expression<Func<Picture, int>> selector = o => o.EntityId;

var parameter = Expression.Parameter(typeof(Picture));

// get property name
if (!(selector.Body is MemberExpression memberExpression))
{
    memberExpression = ((UnaryExpression)selector.Body).Operand as MemberExpression;
}
var propertyName = memberExpression.ToString().Substring(2);

var expressionParameter = Expression.Property(parameter, propertyName);
var expressionBody = Expression.GreaterThan(expressionParameter, Expression.Constant(5, typeof(int)));

var filter = Expression.Lambda<Func<Picture, bool>>(expressionBody, parameter);
var collection = _dbContext.Pictures.Where(filter).ToList();

Общий пример:

var filter = CreateFilter<Picture, int>(o => o.EntityId, 5);
var collection = _dbContext.Pictures.Where(filter).ToList();

private Expression<Func<TData, bool>> CreateFilter<TData, TKey>(Expression<Func<TData, TKey>> selector, TKey valueToCompare)
{
    var parameter = Expression.Parameter(typeof(TData));
    var expressionParameter = Expression.Property(parameter, GetParameterName(selector));

    var body = Expression.GreaterThan(expressionParameter, Expression.Constant(valueToCompare, typeof(TKey)));
    return Expression.Lambda<Func<TData, bool>>(body, parameter);
}

private string GetParameterName<TData, TKey>(Expression<Func<TData, TKey>> expression)
{
    if (!(expression.Body is MemberExpression memberExpression))
    {
        memberExpression = ((UnaryExpression)expression.Body).Operand as MemberExpression;
    }

    return memberExpression.ToString().Substring(2);
}

Благодаря ответу Дэвида о Запретить оценку на стороне клиента я смог убедиться, что фильтрация не выполняется на клиенте

0
Pavel 25 Апр 2020 в 11:55

Сконфигурируйте ваш DbContext, чтобы запретить оценку на стороне клиента и тестирование.

Например

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
        .ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}

См. https://docs.microsoft.com. / EN-US / эф / ядро / поиск / клиент - Eval # предыдущая -версия

Или начните миграцию на EF Core 3.1, который расширил возможности перевода запросов и удалил «функцию» оценки на стороне клиента.

1
David Browne - Microsoft 24 Апр 2020 в 16:59