开发者

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 MemberExpressions :

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.Constantin 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜