Reputation: 287
I am creating an IQueryable that I want to use for a query passed to entity framework. My repository does not expose queryable.
var query = new List<Entity>().AsQueryable().Where(x => x.Property == "argument");
I have a method on my repository that will take in an IQueryable.
How do I query my DbSet with the same queryable? I am trying to extract the expression from the queryable to build a new expression for the dbset. Here is what I have so far but it does not work:
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;
}
The code fails when I try and create the lambda with the following error: Expression of type 'System.Linq.IQueryable`1[MyTEntity]' cannot be used for return type 'System.Boolean'
I'm clearly not building the expression correctly, what am I missing? Is there an easier way to do what I'm trying to accomplish?
Also I've seen some examples that show an Expression should have a parameters property. But no matter what type of expression type I cast to, and this one is ConstantExpression, I don't see a parameters property from the IQueryable.Expression.
Upvotes: 1
Views: 2667
Reputation: 244767
In your case, queryable.Expression
represents the whole expression Queryable.Where(constantList, x => x.Property == "argument")
. If you want just the Where()
lambda, you need to extract it. To do that, you could use code like this:
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;
}
Upvotes: 3