Использование лямбда-выражения для доступа к элементам для параметризации предиката LINQ to SQL - PullRequest
5 голосов
/ 09 августа 2010

У меня есть запрос, который необходимо повторно использовать повсеместно, и мне нужно изменить, какое свойство / столбец используется для объединения.

То, что я хотел бы сделать, это что-то вроде:

query = RestrictByProp(query, x=>x.ID);

Чрезвычайно упрощенным RestrictByProp() может быть *:

private static IQueryable<Role> RestrictByProp(IQueryable<Role> query, 
                                               Func<Role, int> selector)
{
    return query.Where(x => selector(x) == 1);
}

Проблема в том, что даже эта простая реализация вызывает исключение времени выполнения:

Method 'System.Object DynamicInvoke(System.Object[])' has no 
supported translation to SQL.

** (Здесь я просто добавляю простое предложение «где» - в моем реальном коде я бы использовал лямбду, чтобы выбрать, какое свойство использовать для объединения). *

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

 private static IQueryable<Role> RestrictByID(IQueryable<Role> query)
 {
     return query.Where(x=> x.ID == 1);
 }

LINQ to SQL также будет рад, если вы передадите Expression<Func<Role, bool>> (т.е. когда параметр равен x=>x.ID == 1), но это побеждаетобъект, потому что мне нужно, чтобы значение правого операнда было определено в запросе.

Есть ли способ как-то изменить лямбда-выражение в RestrictByProp(), чтобы LINQ to SQL знал, каксгенерировать SQL?

1 Ответ

6 голосов
/ 09 августа 2010

Во-первых, вам нужно изменить сигнатуру вашего метода:

private static IQueryable<Role> RestrictByProp(IQueryable<Role> query, 
    Expression<Func<Role, int>> selector)

Это будет означать, что ваше лямбда-выражение преобразуется в дерево выражений вместо делегата.

Затем вам потребуетсяпостроить Expression<Func<Role, bool>> из существующего дерева выражений.

Это будет выглядеть что-то как это:

LambdaExpression lambda = (LambdaExpression) selector;
var predicate = Expression.Equal(selector, Expression.Constant(1));
var lambdaPredicate = Expression.Lambda<Func<Role, bool>>(predicate,
                                                          lambda.Parameters);
return query.Where(lambdaPredicate);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...