Перевод выражений IQueryable
Я создаю IQueryable, который я хочу использовать для запроса, переданного в платформу сущностей. Мой репозиторий не предоставляет возможность запроса.
var query = new List<Entity>().AsQueryable().Where(x => x.Property == "argument");
У меня есть метод в моем хранилище, который принимает IQueryable.
Как я могу запросить мой DbSet с тем же запросом? Я пытаюсь извлечь выражение из запрашиваемого для создания нового выражения для базы данных. Вот то, что у меня есть, но оно не работает:
public IDbSet<TEntity> DbSet { get; set; }
public IEnumerable<TEntity> Find(IQueryable<TEntity> queryable)
{
var parameter = Expression.Parameter(typeof (TEntity));
var body = queryable.Expression;
var lambda = Expression.Lambda<Func<TEntity, bool>>(body, parameter);
var result = DbSet.Where(lambda);
return null;
}
Код не выполняется, когда я пытаюсь создать лямбду со следующей ошибкой: Выражение типа 'System.Linq.IQueryable`1[MyTEntity]' нельзя использовать для типа возвращаемого значения 'System.Boolean'
Я явно не правильно строю выражение, что мне не хватает? Есть ли более простой способ сделать то, что я пытаюсь сделать?
Также я видел несколько примеров, которые показывают, что выражение должно иметь свойство параметров. Но независимо от того, к какому типу выражения я приведу тип, а это ConstantExpression, я не вижу свойства параметров из IQueryable.Expression.
1 ответ
В твоем случае, queryable.Expression
представляет собой целое выражение Queryable.Where(constantList, x => x.Property == "argument")
, Если вы хотите только Where()
лямбда, тебе нужно извлечь его. Чтобы сделать это, вы можете использовать такой код:
public IEnumerable<TEntity> Find<TEntity>(IQueryable<TEntity> queryable)
{
var methodCall = queryable.Expression as MethodCallExpression;
Func<IQueryable<TEntity>, Expression<Func<TEntity,Boolean>>, IQueryable<TEntity>> whereDelegate = Queryable.Where;
if (methodCall.Method == whereDelegate.Method
&& methodCall.Arguments[0] is ConstantExpression)
{
var whereLambdaQuote = (UnaryExpression)methodCall.Arguments[1];
var whereLambda = (Expression<Func<TEntity, bool>>)whereLambdaQuote.Operand;
var result = DbSet.Where(whereLambda);
}
return null;
}