nhibernate-core
nhibernate-core copied to clipboard
WIP - Support non parameterized constants query plan caching for Linq provider
With this PR query plans for queries like:
db.Customers.Select(o => new {o.CustomerId, Constant = "constant"}).First()
db.Customers.WithLock(LockMode.Upgrade).ToList()
will be cached. This was achieved by adding an additional parameter for item/list/post transformers, which contains all parameter values.
For the following query:
db.Customers.Select(o => new {o.CustomerId, Constant = "constant"}).First()
the selector will be cached as:
(input, parameterValues) => new {CustomerId = input[0], Constant = parameterValues[0]}
before this PR it was cached as:
(input) => new {CustomerId = input[0], Constant = "constant"}.
In order to handle scenarios where a parameter detected by ExpressionParameterVisitor is converted to a hql constant, a special logic was added (VisitorParameters.UpdateCanCachePlan) that check whether all parameters in the expression were converted to hql. One example is TrimGenerator, where char parameter is converted to string and it is used to create a hql constant. In that case the query plan won't be cached.
Added WIP as it is a continuation of #2365.
Possible breaking changes:
- Property
AdditionalCriteriainExpressionToHqlTranslationResultsis not populated anymore,PreQueryExecuteDelegatesproperty has to be used instead - ~Delegate
ExpressionToHqlTranslationResults.PostExecuteTransformergained one parameter of typeobject[]~ - Exceptions that occur when calling Linq
ToFutureValueandToFuturemethods are no longer wrapped insideTargetInvocationException.
Force pushed a version that does not need to alter the IResultTransformer interface (here is the old version). In the current state, a new ExpressionToHqlTranslationResults is created for each execution by using WithParameterValues method, which creates a new ResultTransformer and PostResultTransformer (added in this PR) instance that contain the parameter values. The newly added PostResultTransformer isn't invoked with DynamicInvoke anymore, as it is constructed as Func<object, object[], object>, so exceptions will not be wrapped inside TargetInvocationException anymore. This causes a possible breaking change for ToFutureValue and to ToFuture methods as exceptions were not unwrapped from a TargetInvocationException (Updated description).