I know what a Lambda Expression is.
But I am not sure if that is the same thing as an Expression. There seems to be more to know here than I know.
I am looking at wrapping IQueryable and that uses Expressions a lot. So, for example, is there more to the 'Expression' parameter here than can be thought of in a Lambda?
public InterceptedQuery(InterceptingProvider provider, Expression expression)
{
this._provider = provider;
this._expression = expression;
}
A lambda expression is a compiler feature that is compiled, depending on context, into one of two things:
A (hidden) function and a delegate to it
An Expression
Once the application has been compiled, the concept of a lambda expression doesn't exist, as it's been turned into one of the above two options.
I'm not sure what you mean by
is there more to the 'Expression' parameter here than can be thought of in a Lambda
An expression encapsulates and expressed application logic in an inspectable form (in other words, it lets you see what the developer wrote in terms of properties and functions invoked, constants included, comparisons, etc.). This is how query providers (for the most part, object-relational mappers like the Entity Framework) take code and turn it into SQL.
Lambdas are generally compiled code, where Expression represents "abstract syntax trees" (AST), ie. a data structure that represents code, and can be compiled to code. IQueryable generally operates on Expression because it's supposed to compile the AST to code that runs in different environments, like an SQL server, instead of just the host machine. There are IQueryableProviders that compile to SQL (Linq2Sql), to JavaScript, to OpenGL shaders (Bling), and more.
The C# compiler can sometimes turn a lambda into an expression, if the method parameter expects an expression of the right type:
void Foo(Expression<Func<int>>) { ... }
...
Foo(() => 3);
Related
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)
);
I've read this answer and understood from it the specific case it highlights, which is when you have a lambda inside another lambda and you don't want to accidentally have the inner lambda also compile with the outer one. When the outer one is compiled, you want the inner lambda expression to remain an expression tree. There, yes, it makes sense quoting the inner lambda expression.
But that's about it, I believe. Is there any other use case for quoting a lambda expression?
And if there isn't, why do all the LINQ operators, i.e. the extensions on IQueryable<T> that are declared in the Queryable class quote the predicates or lambdas they receive as arguments when they package that information in the MethodCallExpression.
I tried an example (and a few others over the last couple of days) and it doesn't seem to make any sense to quote a lambda in this case.
Here's a method call expression to a method that expects a lambda expression (and not a delegate instance) as its only parameter.
I then compile the MethodCallExpression by wrapping it inside a lambda.
But that doesn't compile the inner LambdaExpression (the argument to the GimmeExpression method) as well. It leaves the inner lambda expression as an expression tree and does not make a delegate instance of it.
In fact, it works well without quoting it.
And if I do quote the argument, it breaks and gives me an error indicating that I am passing in the wrong type of argument to the GimmeExpression method.
What's the deal? What's this quoting all about?
private static void TestMethodCallCompilation()
{
var methodInfo = typeof(Program).GetMethod("GimmeExpression",
BindingFlags.NonPublic | BindingFlags.Static);
var lambdaExpression = Expression.Lambda<Func<bool>>(Expression.Constant(true));
var methodCallExpression = Expression.Call(null, methodInfo, lambdaExpression);
var wrapperLambda = Expression.Lambda(methodCallExpression);
wrapperLambda.Compile().DynamicInvoke();
}
private static void GimmeExpression(Expression<Func<bool>> exp)
{
Console.WriteLine(exp.GetType());
Console.WriteLine("Compiling and executing expression...");
Console.WriteLine(exp.Compile().Invoke());
}
You have to pass the argument as a ConstantExpression:
private static void TestMethodCallCompilation()
{
var methodInfo = typeof(Program).GetMethod("GimmeExpression",
BindingFlags.NonPublic | BindingFlags.Static);
var lambdaExpression = Expression.Lambda<Func<bool>>(Expression.Constant(true));
var methodCallExpression =
Expression.Call(null, methodInfo, Expression.Constant(lambdaExpression));
var wrapperLambda = Expression.Lambda(methodCallExpression);
wrapperLambda.Compile().DynamicInvoke();
}
private static void GimmeExpression(Expression<Func<bool>> exp)
{
Console.WriteLine(exp.GetType());
Console.WriteLine("Compiling and executing expression...");
Console.WriteLine(exp.Compile().Invoke());
}
The reason should be pretty obvious - you're passing a constant value, so it has to be a ConstantExpression. By passing the expression directly, you're explicitly saying "and get the value of exp from this complicated expression tree". And since that expression tree doesn't actually return a value of Expression<Func<bool>>, you get an error.
The way IQueryable works doesn't really have much to do with this. The extension methods on IQueryable have to preserve all information about the expressions - including the types and references of the ParameterExpressions and similar. This is because they don't actually do anything - they just build the expression tree. The real work happens when you call queryable.Provider.Execute(expression). Basically, this is how the polymorphism is preserved even though we're doing composition, rather than inheritance (/interface implementation). But it does mean that the IQueryable extension methods themselves cannot do any shortcuts - they don't know anything about the way the IQueryProvider is actually going to interpret the query, so they can't throw anything away.
The most important benefit you get from this, though, is that you can compose the queries and subqueries. Consider a query like this:
from item in dataSource
where item.SomeRelatedItem.Where(subItem => subItem.SomeValue == 42).Count() > 2
select item;
Now, this is translated to something like this:
dataSource.Where(item => item.SomeRelatedItem.Where(subItem => subItem.SomeValue == 42).Count() > 2);
The outer query is pretty obvious - we'll get a Where with the given predicate. The inner query, however, is actually going to be a Call to Where, taking the actual predicate as an argument.
By making sure that actual invocations of the Where method are actually translated into a Call of the Where method, both of these cases become the same, and your LINQProvider is that one bit simpler :)
I've actually written LINQ providers that don't implement IQueryable, and which actually have some useful logic in the methods like Where. It's a lot simpler and more efficient, but has the drawback described above - the only way to handle subqueries would be to manually Invoke the Call expressions to get the "real" predicate expression. Yikes - that's quite an overhead for a simple LINQ query!
And of course, it helps you compose different queryable providers, although I haven't actually seen (m)any examples of using two completely different providers in a single query.
As for the difference between Expression.Constant and Expression.Quote themselves, they seem rather similar. The crucial difference is that Expression.Constant will treat any closures as actual constants, rather than closures. Expression.Quote on the other hand, will preserve the "closure-ness" of the closures. Why? Because the closure objects themselves are also passed as Expression.Constant :) And since IQueryable trees are doing lambdas of lambdas of lambdas of [...], you really don't want to lose the closure semantics at any point.
I'm starting to look under the LINQ hood a little more, and I'm having trouble understanding some of the LINQ extension method overloads.
For example, lets say I'm querying a DbContext using .Where(). I'm always passing a standard Func<>, as opposed to an Expression<> of said Func<>. Example query below:
var db = new MyContext();
var foo = db.products.Where(p => p.Category == "books");
Here is where I'm confused. When I look at the available method signatures, I would assume the overload I'm using above would be returning me an IEnumerable...but it's actually returning an IQueryable. How is this possible, if the IQueryable overload is expecting an Expression as opposed to just a Func? It feels like the compiler is somehow helping me out by (in this case) building the Expression for me, but I can't find a resource that explains if this is the case. Thanks!
It feels like the compiler is somehow helping me out by (in this case) building the Expression for me
That is exactly what is happening. The compiler can interpret lambdas (as long as they don't have a "statement body") as either delegates or expression trees. The Queryable.Where<T>(this IQuerayble<T>, ...) extension method takes precedence over the Enumerable.Where<T>(this IEnumerable<T>, ...) extension method, so the compiler chooses to interpret your predicate as an expression tree.
It feels like the compiler is somehow helping me out by (in this case) building the Expression for me
Correct, the compiler is compiling the lambda into an Expression rather than a Func.
I can't find a resource that explains if this is the case
From MSDN:
When a lambda expression is assigned to a variable of type Expression<TDelegate>, the compiler emits code to build an expression tree that represents the lambda expression.
You're not passing a Func in that example. You're passing an Expression. A lambda can compile down into either a delegate or an expression, based on the context around it. In this case the context around it is expecting an expression, so that is what the lambda compiles into. If you actually did pass in a Func and not a lambda (which could be either) then you would get an IEnumerable for your result, not an IQueryable.
The compiler can automatically build an expression tree for you from a lamba expression, and that is what's happening here.
http://msdn.microsoft.com/en-gb/library/bb397951.aspx
I'm having some difficulty creating Lambda-based Linq expressions from a string. Here is my basic case using this sample object/class:
public class MockClass
{
public string CreateBy { get; set; }
}
Basically I need to convert a string like this:
string stringToConvert = “x => x.CreateBy.Equals(filter.Value, StringComparison.OrdinalIgnoreCase”;
Into a to predicate/linq expression:
System.Linq.Expressions.Expression<Func<T, bool>> or in this example
System.Linq.Expressions.Expression<Func<MockClass, bool>>
So it is equivalent to the Linq expression inside of the Where method below:
query = query.Where(x => x.CreateBy.Equals(filter.Value,
StringComparison.OrdinalIgnoreCase));
I've tried using the following helpers but can't seem to figure out how to get them to work in this type of case where I want to be able to build a linq expression from string that is not know ahead of time:
http://www.albahari.com/nutshell/predicatebuilder.aspx
http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx (it’s now available as a NuGet package as well called “DynamicQuery”)
A similar question was asked here:
Is there an easy way to parse a (lambda expression) string into an Action delegate?
As I understand it, this 'Dynamic Query' is actually a framework for passing in restrictions for a Where clause without using a lambda expression.
The significance of that is that lambda expressions are not dynamic methods, they're anonymous methods. If you ever take a look in an assembly, you'll see that your lambda expressions are converted into closures with any free variables as fields. The class has a method with a signature matching yours, field variables are assigned at the point of invocation.
One good way to think about that is that it implies that your lambda expression is interpreted by the c# compiler at compile-time, and variables are resolved by instantiating an object from this class at run-time.
To demonstrate this, consider the following:
var myLambda = x => x * x
You'll notice this doesn't work. That's because, in order to create the related class/method, the compiler must know, at compile-time, the type of x.
All of this is important because the notion of a lambda expression doesn't exist at the CLR at run-time (in the same form it is in code). A string that looks like a lambda expression is exactly that...
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.