Pascal Amey
Pascal Amey

Reputation: 213

How to declare a Linq Expression variable in order to have it processed as a dbParameter

I'm trying to create dynamic queries against Entity framework (or other Linq provider).

Let me explain my problem with some sample code.

If I hardcode an expression :

var id = 12345;

Expression<Func<ItemSearch, bool>> myLambda = (s) => s.Id == id;

var finalQuery = context.ItemSearch.Where(myLambda);
this.Log((finalQuery as ObjectQuery).ToTraceString());

The generated SQL looks like this :

SELECT ...
FROM ViewItemSearch "Extent1"
WHERE "Extent1".ID = :p__linq__0

with a nice :p__linq__0 dbParameter.

If I create an expression :

var id = 12345;
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s");
Expression prop = Expression.Property(param, "Id");
Expression val = Expression.Constant(id);
Expression searchExpr = Expression.Equal(prop, val);

Expression<Func<ItemSearch, bool>> myLambda =  
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr , param);

var finalQuery = context.ItemSearch.Where(myLambda);
this.Log((finalQuery as ObjectQuery).ToTraceString());

The generated SQL looks like this :

SELECT ...
FROM ViewItemSearch "Extent1"
WHERE "Extent1".ID = 12345

No more :p__linq__0 dbParameter so the Db engine cannot cache query plans.

I understand that it is because I use

Expression val = Expression.Constant(id);

But I can't figure out how to bind a variable instead of the value.

Upvotes: 10

Views: 10213

Answers (1)

Servy
Servy

Reputation: 203827

You'll need to create a lambda at compile time to close over the id variable, to which you can then grab the body of an use in the composition of your more complex lambda:

var id = 12345;
ParameterExpression param = Expression.Parameter(typeof(ItemSearch), "s");
Expression prop = Expression.Property(param, "Id");
Expression<Func<int>> idLambda = () => id;
Expression searchExpr = Expression.Equal(prop, idLambda.Body);

Expression<Func<ItemSearch, bool>> myLambda =
    Expression.Lambda<Func<ItemSearch, bool>>(searchExpr, param);

Upvotes: 10

Related Questions