C# Expression Trees - Dynamic Value Lookup - c#

I'm building a C# expression tree to evaluate simple expressions. The expression strings are parsed into trees, and respect the basic operators (mathematical, logical and relational) as well as precedence through the use of parantheses.
In addition to the types bool, string and integer - I require some of the elements of the expression to be evaluated at runtime. These are represented by templated strings, for example:
([firstname] == "bob") && ([surname] == "builder")
The above expression would be evaluated for a (potentially large) number of objects that provide the context for the current expression invocation, for example, in a loop. The templated section would be used reflectively on the current context - e.g. the current user's firstname and surname would be resolved in the example and those values used in the expression resolution rather than the templated strings.
One solution would be to resolve the templated value at parse time, that way a constant expression type could be used and the type of the value would be known. However, re-building and re-compiling the expression tree each use would have bad for performance.
So, I need an expression type whose:
- value type is not known at parse time, and
- which is resolved by a method call at invoke time
E.g. Desired example of usage in pseudo code
ExpressionParser parser = new ExpressionParser(); // parses and builds expression trees
MyParsedExpression expression = parser.Parse("([firstname] == 'bob') && ([surname] == 'builder'"); // wrapper for the parsed expression
foreach (Object user in users)
{
expression.Context = user;
Boolean result = expression.EvaluateTruth();
if (result == true)
{
// do something
}
}
Thanks,
fturtle

Use a ParameterExpression to represent an incoming parameter. As for the type exception... do you know the type of the data when you build the expression tree? If not, that does make things a lot harder...
If it's any use to you, I answered a similar question recently, with some source code. It may not be immediately usable to you, but it should be a good start.
EDIT: I'm not sure that expression trees are going to be very much use to you here. In particular a PropertyExpression contains the relevant PropertyInfo, so it needs to know the type it's working with. If the type could change for every value, you'd have to rebuild the expression tree for every value...

Related

The binary operator Equal is not defined for the types 'System.Int32' and 'System.Object'

I want to build the following expression:
myObj.Id == null
myObj.Id is a non-nullable int. I know that if this expression is evaluated literally then the result will always be false, but I need to build this expression because an expression visitor will later examine it and do something with it.
It's perfectly possible to write this expression literally in your code, but when I try to dynamically build it with the following factory method:
Expression.Equal(left: /* myObj.Id */, right: /* anotherId */);
I get the following exception:
The binary operator Equal is not defined for the types 'System.Int32' and 'System.Object'.
This doesn't make sense since it's possible to write the very same expression literally in C#.
How can I generate that expression? <int> == null?
How can I generate that expression? == null?
The compiler promotes the int to a nullable type, i.e. Nullable<int>, also known as int?. You would need to do the same.
As a general technique, it is often helpful to use the compiler itself to show you how to build an Expression object that does what you want. For example, to answer your specific question, how to generate that expression, just write the expression you want, compile it, and run it in the debugger so you can look to see what the compiler did:
Expression<Func<int, bool>> ex = i => i == null;
If you do that, you will find an expression that has a Body value of "(Convert(i) == null)". That is, the node type is Equal, the right operand is null, and the left operand is a Convert node, the operand of which is the int value i, and the destination type of which is Nullable<int>.
With that information in hand, it should be relatively easy now to write the C# code that will actually build that expression. Of course, an alternative is to just use the declaration above (or something similar) and always let the compiler build the Expression object for you. I personally prefer to not write Expression-building code if I can help it. It's very verbose and error-prone, so any time the compiler can do the work for me (which is very often), I let it.

Evaluator.PartialEval reduce provided expression

In one of my projects I have an ExpressionVisitor to translate provided expression into some query string. But before translating it I need to evaluate all refferences in the expression to real values. To do that I use Evaluator.PartialEval method from EntityFramework Project.
Assuming I have this query:
var page = 100;
var query = myService.AsQueryable<Product>()
//.Where(x=>x.ProductId.StartsWith(p.ProductId))
.Skip(page)
.Take(page);
var evaluatedQueryExpr = Evaluator.PartialEval(query.Expression);
As you can see I have commented Where method. In this case evaluatedQueryExpr will not contain the methods Take and Skip.
However, if I use any other method with Expression before Take or Skip everything works, Evaluator evaluates an expression correctly and return it fully.
I found out that the problem occurs in the line 80 of the Evaluator class:
return Expression.Constant(fn.DynamicInvoke(null), e.Type);
Could you explain why this happens and suggest a workaround?
Update
here is a project on github
LinqToSolrQueriable inherited from IOrderedQueryable
LinqToSolrProvider inherited from IQueryProvider including line range causing the issue
The good news are that the expression is not really reduced (Skip and Take are still there :), but is simply converted from MethodCallExpression to ConstantExpression containing the original expression:
query.Expression:
.Call System.Linq.Queryable.Take(
.Call System.Linq.Queryable.Skip(
.Constant<LinqToSolr.Query.LinqToSolrQueriable`1[LinqToSolrTest.Product]>(LinqToSolr.Query.LinqToSolrQueriable`1[LinqToSolrTest.Product]),
100),
100)
evaluatedQueryExpr:
.Constant<System.Linq.IQueryable`1[LinqToSolrTest.Product]>(LinqToSolr.Query.LinqToSolrQueriable`1[LinqToSolrTest.Product])
Here the debug display is giving you a wrong impression. If you take the ConstaintExpression.Value, you'll see that it's a IQueryable<Product> with Expression property being exactly the same as the original query.Expression.
The bad news are that this is not what you expect from PartialEval - in fact it doesn't do anything useful in this case (except potentially breaking your query translation logic).
So why is this happening?
The method you are using from EntityFramework.Extended library is in turn taken (as indicated in the comments) from MSDN Sample Walkthrough: Creating an IQueryable LINQ Provider. It can be noticed that the PartialEval method has two overloads - one with Func<Expression, bool> fnCanBeEvaluated parameter used to identify whether a given expression node can be part of the local function (in other words, to be partially evaluated or not), and one without such parameter (used by you) which simply calls the first passing the following predicate:
private static bool CanBeEvaluatedLocally(Expression expression)
{
return expression.NodeType != ExpressionType.Parameter;
}
The effect is that it stops evaluation of ParameterExpression type expressions and any expressions containing directly or indirectly ParameterExpression. The last should explain the behavior you are observing. When the query contains Where (and basically any LINQ operator) with parametrized lambda expression (hence parameter) before the Skip / Take calls, it would stop evaluation of the containing methods (which you can see from the above query.Expression debug view - the Where call will be inside the Skip).
Now, this overload is used by the MSDN example to evaluate a concrete nested Where method lambda expression and is not generally applicable for any type of expression like IQueryable.Expression. In fact the linked project is using the PartialEval method in a single place inside QueryCache class, and also calling the other overload passing a different predicate which in addition to ParameterExpressions stops the evaluation of any expression with result type of IQueryable.
Which I think is the solution of your problem as well:
var evaluatedQueryExpr = Evaluator.PartialEval(query.Expression,
// can't evaluate parameters or queries
e => e.NodeType != ExpressionType.Parameter &&
!typeof(IQueryable).IsAssignableFrom(e.Type)
);

What does the Expression<Func<T,bool>> declaration mean?

Could somebody explain the following declaration in a way that conveys the meaning of the expression and how it would be called?
void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new();
I read it as:
Delete an object of type T, by passing in a lambda expression whose parameter is an object of type T that returns a bool.
Also, can you replace
Func<T, bool> expression
with
Predicate<T> expression
This method is probably a member of a collection type, yes?
A "predicate" is any device that says "yes" or "no" to the question "is this thing a member of that set?" So a predicate for the set "integers even positive integers" would be x=> x > 0 && x % 2 == 0.
This method probably has the semantics of "delete from the collection all members of the collection that are in the set identified by the predicate".
The predicate is passed to the method in the form of an expression tree, which is a way of passing the structure of the predicate in a manner that can be analyzed at runtime and transformed. It is typically used in scenarios where the "collection" is actually a database somewhere, and the deletion request needs to be translated into a query in the database's query language and sent over the network.
The first is a method which accepts an expression tree (not necessarily created from a lambda expression tree). The expression tree represents an expression which accepts a T and returns a bool. T is constrained to be a reference type with a parameterless constructor.
As for the semantic meaning - that's up to the documentation/implementation.
It's important to distinguish between a lambda expression, which is one way of creating an expression tree, and an expression tree itself.
As for whether it could use Predicate<T> instead - maybe. It depends on what the implementation does with it. They represent the same delegate signature, certainly - but you can't convert between the two types of expression tree trivially.
this methods gets as a parameter expression tree of function that gets object with public parameter-less constructor and returns boolean.
you can read more about expression trees and their usage here:
http://msdn.microsoft.com/en-us/library/bb397951.aspx
While the method signature looks invalid to me, essentially you are passing in an expression tree (it might not be a LambdaExpression type as Expression is the abstract base class for all expression types).
The type constraints state that T must be a reference type (inherit from a class, cannot be a value type (read: struct)) and must also have a default constructor defined.
EDIT: see Jon's answer below, he corrected the signature and answered the question correctly from there, providing more information than I.

Expression trees for code which doesn't type check

Is it possible to construct an expression tree in .NET 3.5 from code like
Expression expr = () => (true + new object())
? It seems to be impossible, since "A compiler-generated expression tree is always rooted in a node of type Expression", but I may be missing something.
Obviously, such a tree can be constructed manually.
No it is not obvious that such a tree can be constructed manually. The expression the tree is representing is type-checked as it is being constructed. As such, what you ask is not possible and the answer is no.

How can I build LINQ query when object type is not known at compile-time

I am developing Web Custom control which able to apply filters to the LinqDataSource object. It is generic control since it should operate with object of certain type.
The control knows what field of object it should operate by following field
/// <summary>
/// Method to get compared column from object
/// </summary>
public Expression<Func<T, int>> GetColumnMethod;
(I transfer to it method which gets appropriate field from object type)
We perform the filtering with code like that
... if (selectedValue == "<=")
predicate = predicate.And(c => method(c) <= val);
if (selectedValue == "<")
predicate = predicate.And(c => method(c) < val);
All proceeds OK until LINQ to SQL transformation occurs.
Then error "Method '.....' has no supported translation to SQL.
sure, CLR doesn't know how to make SQL for delegates.
If only C# could compile the expression before translation to SQL, but I have no idea how to make it to do it.
Perversions like Expression.Compile (whatever tricky ways I tried the whole day - I already cannot remember them all...nothing helped)
But ... at the runtime CLR already knows the type of my object, so it could to manage to build SQL expression having compiked delegate values. But how to do it ? God knows.
Help highly appreciates.
The LINQ to SQL provider is responsible for translation your expression tree into a valid T-SQL statement. As there is not a 1-to-1 relationship between C# and T-SQL it is highly probable that the more sophisticated your expression tree, the less likely it is that LINQ to SQL will be able to translate.
When you use a lambda expression you have to decide if you want to compile it or use it as an expression tree. If you want to use the lambda as an expression then you are responsible for ensuring that the expression contains functions and syntax that your provider supports.
It won't work. Basically your LINQ query is valid C# code so it compiles fine but it fails during runtime on anything outside of scope of LINQ to SQL provider.
Read more here:
“Cannot call methods on DateTime”, and other limitations
If it's just a matter of selecting a particular field to use in your query, you should be able to do this using the Expression.Compile "perversion". But that's likely to be a lot of work. You can probably get a head start by compiling what you have now and using Reflector against the output to see what the code generated by the C# compiler looks like.
Can you split the query into two parts -- one that gets translated to SQL and runs on the server and one that uses your GetColumnMethod and runs in memory against the data output by the first part?
There is no SQL for arbitrary delegates. If method(c) can be expressed as a lambda, you can invoke the lambda as a sub-expression using Expression.Invoke, but you'd need to build the expression tree yourself, like so.

Categories