Построить выражение для фильтрации данных EF Core - PullRequest
0 голосов
/ 24 апреля 2020

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

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

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

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

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

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

var collection = _dbContext.Pictures.Where(filter).ToList();

Ответы [ 2 ]

1 голос
/ 24 апреля 2020

Сконфигурируйте ваш 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/ef/core/querying/client-eval#previous -версии

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

0 голосов
/ 25 апреля 2020

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

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();

Generi c пример:

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);
}

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

...