twifosp
twifosp

Reputation: 287

IQueryable Expression Translation

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

Answers (1)

svick
svick

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

Related Questions