Lambda expressions on constants could not be evaluated because all parameters are considered non-evaluatable, which causes e.g. NHibernate issue #2276.
Relevant classes required to override this behavior are sealed and duplication of Relinq code in target project is required.
Change is proposed in pull request #14.
To preserve existing behavior new method 'IsEvaluatableParameter' is added to IEvaluatableExpressionFilter and its default implementation in EvaluatableExpressionFilterBase shuts down evaluation of all expressions involving parameters. If overridden, the EvaluatableTreeFindingExpressionVisitor will determine whether parameter can be considered evaluatable by looking up the lambda expression defining it.
Thank you for starting the ticket. Now we can get things rolling. The ticket description right now actually describes/duplicates your PR. Some implementation details in the ticket could be replaced with a sample query that show cases the scenario described in the first sentence. We'll also be documenting the changes / extensions to the IEvaluatableExpressionFilter you got started to describe here.
From the idea, it should be noted that not having this isn't a show stopper, it's always possible to pull out the relevant bits and evaluate them outside of the LINQ statement, simply passing in the result. In case it's blocking someone right now.
As for the convenience feature, yes, this should be helpful when writing queries without much fuzz about what works and what doesn't and how to fix it. It can be expected to be able to evaluate the parameter expression in memory, provided it is closed (doesn't have any dependencies to other parameters or the query itself). This will be the core focus of a) the impelmentation, b) the tests, and c) the review itself in the PR.
I've taken the chance and looked at the API, and there's the following Expression types missing:
We will probably want to add filter methods for all those types when we change the interface in order to do one big change that makes the API future proof. Depending on the release plans, we might also want to check of .NET Standard 2.1 introduced additional types directly derived from System.Linq.Expressions.Epression.
Might have further comments down the line.
Considering things further, I believe that is a duplicate of this feature request as it concerns parameter expressions. could you please check this against the spec in RMLNQ-96? Thank you.
PS: I've linked this for now to keep the reference visible.
The library undertakes to 'evaluate independent subtrees' and IEvaluatableExpressionFilter has a method IsEvaluatableLambda which by default returns true; what’s the point if any parameter renders it non-evaluatable? The following comment
Evaluates an evaluatable <see cref="Expression"/> subtree, i.e. an independent expression tree that is compilable and executable without any data being passed in.
does not include a disclaimer for any IEnumerable extension methods involving lamda expressions that can clearly be evaluated independently.
These and possibly other factors, I think, contribute to expectation that e.g. simple manipulations on collection parameters would be handled by Relinq. Hence the failure to evaluate clearly evaluatable expressions could even be considered a bug IMO.
In NHibernate the issue can cause undetected bugs (up to incorrect query with no error or warning reported) such as reported in this comment.
I could easily understand someone who would consider it as a severe if not blocker issue. NHibernate cannot force every dependent project to rewrite their queries (evaluate expressions on constants outside query expressions). If relevant classes were pubic and not sealed it would be easy to override and work around the issue, but as it stands that requires copy-pasting some code which is not elegant and bad for maintainability.
Parameter expressions are special because they are just placeholders populated by other lambda expression parameters. They cannot be analyzed independently of the lambda expression defining them.
I attempted to explain the reasoning behind implementation in xmldoc comments, in particular for methods EvaluatableTreeFindingExpressionVisitor.IsMethodSupplyingEvaluatableParameterValues and CalcParameterStatus.
Yes, RMLNQ-96 looks similar.