nhibernate-core icon indicating copy to clipboard operation
nhibernate-core copied to clipboard

WIP - Support non parameterized constants query plan caching for Linq provider

Open maca88 opened this issue 5 years ago • 1 comments

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 AdditionalCriteria in ExpressionToHqlTranslationResults is not populated anymore, PreQueryExecuteDelegates property has to be used instead
  • ~Delegate ExpressionToHqlTranslationResults.PostExecuteTransformer gained one parameter of type object[]~
  • Exceptions that occur when calling Linq ToFutureValue and ToFuture methods are no longer wrapped inside TargetInvocationException.

maca88 avatar May 09 '20 14:05 maca88

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

maca88 avatar May 16 '20 21:05 maca88