Building an expression tree raises an InvalidPathException

I am Expression<Func<PlainAddress, bool>> predicate 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 is working 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)60ee8287-3f42-426a-8c15-41f62f58623c, p1))), )] 

What am I doing wrong? What is the difference between these two options?

+4
source share
1 answer

I am not familiar with NHibernate, but I can try to explain the differences between the two expressions.

1. The main difference is the use of Expression.Invoke in Example # 2, which creates an InvocatonExpression that "represents an expression that applies a delegate or lambda expression to the list of argument expressions." This introduces a kind of indirect attitude - fluent,

Sample No. 1:

 y => y.Address.City == geoObject.Name; 

whereas example 2 looks something like this:

 x => new Func<PlainAddress, string>(y => y.Address.City).Invoke(x) == geoObject.Name 

You can get the second sample closer to the first using Expression.Property to create the corresponding MemberExpression :

 var predicate = Expression.Lambda<Func<PlainAddress, bool>>( Expression.Equal( Expression.Property(Expression.Property(x, "Address"), "City"), Expression.Constant(geoObject.Name)), x); 

Now it is closer to:

 x => x.Address.City == AsStringLiteral(geoObject.Name) 

(I assume this will be enough for the predicate to work with NHibernate.)


2. Another difference, of course, is the use of Expression.Constant in example # 2, which will readily evaluate the value of geoObject.Name and turn it into a literal in the expression tree. You will need much more work if you want to "emulate" the rise of the geoObject variable (or perhaps this ?), As in example No. 1.

+5
source

Source: https://habr.com/ru/post/1335853/


All Articles