Constructing an expression tree causes InvalidPathException
I'm constructing an expression tree (Expression<Func<PlainAddress, bool>> predicate
) to pass it to the IQueryable.Where
function for HNibernate to execute the query. When I pass:
predicate = y => y.Address.City == geoObject.Name;
everything works fine. When I pass:
var x = Expression.Parameter(typeof(PlainAddress));
Expression<Func<PlainAddress, string>> expression = y => y.Address.City;
predicate = Expression.Lambda<Func<PlainAddress, bool>>(
Expression.Equal(
Expression.Invoke(expression, x),
Expression.Constant(geoObject.Name)),
x);
I get the following exception
Invalid path: 'y.Address.City'
[.Where(NHibernate.Linq.NhQueryable`1[BPPDicsManager.Domain.Entities.PlainAddress],
Quote((60ee8287-3f42-426a-8c15-41f62f58623c, ) => (String.op_Equality((y, ) =>
(y.Address.City)60e开发者_如何学JAVAe8287-3f42-426a-8c15-41f62f58623c, p1))), )]
What am I doing wrong? What are the difference between these 2 options?
I'm not familiar with NHibernate, but I can try to explain the differences between the two expressions.
1.The major difference is the use of Expression.Invoke
in sample # 2, which creates an InvocatonExpression
that "represents an expression that applies a delegate or lambda expression to a list of argument expressions". This introduces a kind of indirection - loosely speaking,
Sample # 1 is:
y => y.Address.City == geoObject.Name;
whereas Sample # 2 is something like:
x => new Func<PlainAddress, string>(y => y.Address.City).Invoke(x)
== geoObject.Name
You can get the second sample closer to the first by using Expression.Property
to create the appropriate MemberExpression
s :
var predicate = Expression.Lambda<Func<PlainAddress, bool>>(
Expression.Equal(
Expression.Property(Expression.Property(x, "Address"), "City"),
Expression.Constant(geoObject.Name)),
x);
This is now closer to:
x => x.Address.City == AsStringLiteral(geoObject.Name)
(I'm guessing this will be sufficient to get the predicate to work with NHibernate.)
2.The other difference of course, is the use of Expression.Constant
in sample # 2, which will eagerly evaluate the value of geoObject.Name
and turn that into a literal in the expression-tree. You're going to need a lot more work if you want to 'emulate' the hoisting of the geoObject
variable (or perhaps this
?) as in sample # 1.
精彩评论