Пример #1
0
        public override Expression VisitExpression(Expression expression)
        {
            // Only evaluate expressions which do not use any of the surrounding parameter expressions. Don't evaluate
            // lambda expressions (even if you could), we want to analyze those later on.
            if (expression == null)
            {
                return(null);
            }

            if (expression.NodeType == ExpressionType.Lambda || !_partialEvaluationInfo.IsEvaluatableExpression(expression))
            {
                return(base.VisitExpression(expression));
            }

            Expression evaluatedExpression;

            try
            {
                evaluatedExpression = EvaluateSubtree(expression);
            }
            catch (Exception ex)
            {
                // Evaluation caused an exception. Skip evaluation of this expression and proceed as if it weren't evaluable.
                var baseVisitedExpression = base.VisitExpression(expression);
                // Then wrap the result to capture the exception for the back-end.
                return(new PartialEvaluationExceptionExpression(ex, baseVisitedExpression));
            }

            if (evaluatedExpression != expression)
            {
                return(EvaluateIndependentSubtrees(evaluatedExpression));
            }

            return(evaluatedExpression);
        }
 public override Expression Visit(Expression expression)
 {
     if (expression == null)
     {
         return(null);
     }
     if (expression.NodeType != ExpressionType.Lambda)
     {
         if (_partialEvaluationInfo.IsEvaluatableExpression(expression))
         {
             Expression subtree;
             try
             {
                 subtree = EvaluateSubtree(expression);
             }
             catch (Exception ex)
             {
                 return(new PartialEvaluationExceptionExpression(ex, base.Visit(expression)));
             }
             if (subtree != expression)
             {
                 return(EvaluateIndependentSubtrees(subtree));
             }
             return(subtree);
         }
     }
     return(base.Visit(expression));
 }
 public override Expression VisitExpression(Expression expression)
 {
     // Only evaluate expressions which do not use any of the surrounding parameter expressions. Don't evaluate
     // lambda expressions (even if you could), we want to analyze those later on.
     if (expression == null)
     {
         return(null);
     }
     else if (expression.NodeType != ExpressionType.Lambda && _partialEvaluationInfo.IsEvaluatableExpression(expression))
     {
         var evaluatedExpression = EvaluateSubtree(expression);
         if (evaluatedExpression != expression)
         {
             return(EvaluateIndependentSubtrees(evaluatedExpression));
         }
         else
         {
             return(evaluatedExpression);
         }
     }
     else
     {
         return(base.VisitExpression(expression));
     }
 }
Пример #4
0
        protected override Expression VisitMember(MemberExpression memberExpression)
        {
            if (!_partialEvaluationInfo.IsEvaluatableExpression(memberExpression))
            {
                return(base.VisitMember(memberExpression));
            }

            if (!_queryableTypeInfo.IsAssignableFrom(memberExpression.Type.GetTypeInfo()))
            {
                return(TryExtractParameter(memberExpression));
            }

            string _;
            var    queryable = (IQueryable)Evaluate(memberExpression, out _);

            return(ExtractParameters(queryable.Expression));
        }
Пример #5
0
        public override Expression Visit(Expression expression)
        {
            // Only evaluate expressions which do not use any of the surrounding parameter expressions. Don't evaluate
            // lambda expressions (even if you could), we want to analyze those later on.
            if (expression == null)
            {
                return(null);
            }

            if (expression.NodeType == ExpressionType.Lambda || !_partialEvaluationInfo.IsEvaluatableExpression(expression) ||
                #region NH additions
                // Variables should be evaluated only when they are part of an evaluatable expression (e.g. o => string.Format("...", variable))
                expression is UnaryExpression unaryExpression &&
                ExpressionsHelper.IsVariable(unaryExpression.Operand, out _, out _))
            #endregion
            { return(base.Visit(expression)); }

            Expression evaluatedExpression;
            try
            {
                evaluatedExpression = EvaluateSubtree(expression);
            }
            catch (Exception ex)
            {
                // Evaluation caused an exception. Skip evaluation of this expression and proceed as if it weren't evaluable.
                var baseVisitedExpression = base.Visit(expression);

                throw new HibernateException($"Evaluation failure on {baseVisitedExpression}", ex);
            }

            if (evaluatedExpression != expression)
            {
                evaluatedExpression = EvaluateIndependentSubtrees(evaluatedExpression, _preTransformationParameters);
            }

            #region NH additions

            // When having multiple level closure, we have to evaluate each closure independently
            if (evaluatedExpression is ConstantExpression constantExpression)
            {
                evaluatedExpression = VisitConstant(constantExpression);
            }

            // Variables in expressions are never a constant, they are encapsulated as fields of a compiler generated class.
            if (expression.NodeType != ExpressionType.Constant &&
                _preTransformationParameters.MinimizeParameters &&
                evaluatedExpression is ConstantExpression variableConstant &&
                !_preTransformationParameters.QueryVariables.ContainsKey(variableConstant) &&
                ExpressionsHelper.IsVariable(expression, out var path, out var closureContext))
            {
                _preTransformationParameters.QueryVariables.Add(variableConstant, new QueryVariable(path, closureContext));
            }

            #endregion

            return(evaluatedExpression);
        }
Пример #6
0
        /// <remarks>
        ///		Parameters are evaluatable if they are supplied by evaluatable expression.
        ///		Look up lambda defining the parameter, up the ancestor list and check if method call to which it is passed is on evaluatable
        ///		instance or extension method accepting evaluatable arguments.
        ///		Note that lambda body is visited prior to parameters.
        ///		Since method call is visited in the order [instance, arguments] and extension methods get instance as first parameter
        ///		the source of the parameter is already visited and its evaluatability established.
        /// </remarks>>
        private ParameterStatus CalcParameterStatus(ParameterExpression expression)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }

            var result = new ParameterStatus {
                Expression = expression
            };

            foreach (var ancestor in _ancestors)
            {
                if (result.MethodArgumentAcceptingLambda == null && IsParameterOwner(ancestor, expression))
                {
                    result.MethodArgumentAcceptingLambda = result.OwningExpression = (LambdaExpression)ancestor;
                }
                else if (result.MethodArgumentAcceptingLambda != null)
                {
                    if (ancestor.NodeType == ExpressionType.Call)
                    {
                        result.MethodCallInvokingLambda = (MethodCallExpression)ancestor;

                        result.IsEvaluatable = result.MethodCallInvokingLambda.Object != null
                                                        ? PartialEvaluationInfo.IsEvaluatableExpression(result.MethodCallInvokingLambda.Object)
                                                        : result.MethodCallInvokingLambda.Arguments.All(a => a == result.MethodArgumentAcceptingLambda || (
                                                                                                            PartialEvaluationInfo.IsEvaluatableExpression(a)
                                                                                                            // member expressions on e.g. repository creating query instances must be evaluated into constants
                                                                                                            // but parameters accepting values from them are not evaluatable
                                                                                                            && !typeof(IQueryable).IsAssignableFrom(a.Type)));

                        return(result);
                    }

                    result.MethodArgumentAcceptingLambda = ancestor;
                }
            }

            return(result);
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
        {
            var methodInfo    = methodCallExpression.Method;
            var declaringType = methodInfo.DeclaringType;

            if (declaringType == typeof(Queryable) ||
                declaringType == typeof(EntityFrameworkQueryableExtensions) &&
                (!methodInfo.IsGenericMethod ||
                 !methodInfo.GetGenericMethodDefinition()
                 .Equals(EntityFrameworkQueryableExtensions.StringIncludeMethodInfo)))
            {
                return(base.VisitMethodCall(methodCallExpression));
            }

            var returnTypeInfo = methodInfo.ReturnType.GetTypeInfo();

            if (returnTypeInfo.IsGenericType &&
                returnTypeInfo.GetGenericTypeDefinition() == typeof(DbSet <>))
            {
                var queryable = (IQueryable)Evaluate(methodCallExpression, out _);

                return(ExtractParameters(queryable.Expression));
            }

            if (_partialEvaluationInfo.IsEvaluatableExpression(methodCallExpression))
            {
                if (_queryableTypeInfo.IsAssignableFrom(methodCallExpression.Type))
                {
                    var queryable = (IQueryable)Evaluate(methodCallExpression, out _);

                    return(ExtractParameters(queryable.Expression));
                }

                return(TryExtractParameter(methodCallExpression));
            }

            if (!methodInfo.IsStatic)
            {
                return(base.VisitMethodCall(methodCallExpression));
            }

            ParameterInfo[] parameterInfos = null;
            Expression[]    newArguments   = null;

            var arguments = methodCallExpression.Arguments;

            for (var i = 0; i < arguments.Count; i++)
            {
                var argument    = arguments[i];
                var newArgument = Visit(argument);

                if (newArgument != argument)
                {
                    if (newArguments == null)
                    {
                        parameterInfos = methodInfo.GetParameters();
                        newArguments   = new Expression[arguments.Count];

                        for (var j = 0; j < i; j++)
                        {
                            newArguments[j] = arguments[j];
                        }
                    }

                    if (parameterInfos[i].GetCustomAttribute <NotParameterizedAttribute>() != null)
                    {
                        if (newArgument.RemoveConvert() is ParameterExpression parameter)
                        {
                            var parameterValue = _parameterValues.RemoveParameter(parameter.Name);

                            if (parameter.Type == typeof(FormattableString))
                            {
                                if (Evaluate(methodCallExpression, out _) is IQueryable queryable)
                                {
                                    var oldInLambda = _inLambda;

                                    _inLambda = false;

                                    try
                                    {
                                        return(ExtractParameters(queryable.Expression));
                                    }
                                    finally
                                    {
                                        _inLambda = oldInLambda;
                                    }
                                }
                            }
                            else
                            {
                                var constantParameterValue = Expression.Constant(parameterValue);

                                if (newArgument is UnaryExpression unaryExpression &&
                                    unaryExpression.NodeType == ExpressionType.Convert)
                                {
                                    newArgument = unaryExpression.Update(constantParameterValue);
                                }
                                else
                                {
                                    newArgument = constantParameterValue;
                                }
                            }
                        }
                    }

                    newArguments[i] = newArgument;
                }
Пример #8
0
        public override Expression Visit(Expression expression)
        {
            if (expression == null)
            {
                return(null);
            }

            if (expression.NodeType == ExpressionType.Lambda ||
                !_partialEvaluationInfo.IsEvaluatableExpression(expression))
            {
                return(base.Visit(expression));
            }

            var e = expression;

            if (expression.NodeType == ExpressionType.Convert)
            {
                if (expression.RemoveConvert() is ConstantExpression)
                {
                    return(expression);
                }

                var unaryExpression = (UnaryExpression)expression;

                if ((unaryExpression.Type.IsNullableType() &&
                     !unaryExpression.Operand.Type.IsNullableType()) ||
                    unaryExpression.Type == typeof(object))
                {
                    e = unaryExpression.Operand;
                }
            }

            if (!typeof(IQueryable).GetTypeInfo().IsAssignableFrom(e.Type.GetTypeInfo()))
            {
                var constantExpression = e as ConstantExpression;

                if (constantExpression == null ||
                    (constantExpression.Type != typeof(string) &&
                     constantExpression.Type != typeof(byte[]) &&
                     constantExpression.Value is IEnumerable))
                {
                    try
                    {
                        string parameterName;

                        var parameterValue = ExpressionEvaluationHelpers.Evaluate(e, out parameterName);

                        if (parameterName == null)
                        {
                            parameterName = "p";
                        }

                        var compilerPrefixIndex = parameterName.LastIndexOf(">", StringComparison.Ordinal);

                        if (compilerPrefixIndex != -1)
                        {
                            parameterName = parameterName.Substring(compilerPrefixIndex + 1);
                        }

                        parameterName
                            = $"{CompiledQueryCache.CompiledQueryParameterPrefix}{parameterName}_{_queryContext.ParameterValues.Count}";

                        _queryContext.ParameterValues.Add(parameterName, parameterValue);

                        return(e.Type == expression.Type
                            ? Expression.Parameter(e.Type, parameterName)
                            : (Expression)Expression.Convert(
                                   Expression.Parameter(e.Type, parameterName),
                                   expression.Type));
                    }
                    catch (Exception exception)
                    {
                        throw new InvalidOperationException(
                                  CoreStrings.ExpressionParameterizationException(expression),
                                  exception);
                    }
                }
            }

            return(expression);
        }
        /// <summary>
        ///     This API supports the Entity Framework Core infrastructure and is not intended to be used
        ///     directly from your code. This API may change or be removed in future releases.
        /// </summary>
        protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
        {
            var methodInfo    = methodCallExpression.Method;
            var declaringType = methodInfo.DeclaringType;

            if (declaringType == typeof(DbContext))
            {
                return(methodCallExpression);
            }

            if (declaringType == typeof(Queryable) ||
                (declaringType == typeof(EntityFrameworkQueryableExtensions) &&
                 (!methodInfo.IsGenericMethod ||
                  methodInfo.GetGenericMethodDefinition() != EntityFrameworkQueryableExtensions.StringIncludeMethodInfo)))
            {
                return(base.VisitMethodCall(methodCallExpression));
            }

            if (_partialEvaluationInfo.IsEvaluatableExpression(methodCallExpression))
            {
                return(TryExtractParameter(methodCallExpression));
            }

            if (!methodInfo.IsStatic)
            {
                return(base.VisitMethodCall(methodCallExpression));
            }

            ParameterInfo[] parameterInfos = null;
            Expression[]    newArguments   = null;

            var arguments = methodCallExpression.Arguments;

            for (var i = 0; i < arguments.Count; i++)
            {
                var argument    = arguments[i];
                var newArgument = Visit(argument);

                if (newArgument != argument)
                {
                    if (newArguments == null)
                    {
                        parameterInfos = methodInfo.GetParameters();
                        newArguments   = new Expression[arguments.Count];

                        for (var j = 0; j < i; j++)
                        {
                            newArguments[j] = arguments[j];
                        }
                    }

                    if (parameterInfos[i].GetCustomAttribute <NotParameterizedAttribute>() != null)
                    {
                        var parameter = newArgument.RemoveConvert() as ParameterExpression;

                        if (parameter != null)
                        {
                            newArgument = Expression.Constant(_queryContext.RemoveParameter(parameter.Name));
                        }
                    }

                    newArguments[i] = newArgument;
                }
                else if (newArguments != null)
                {
                    newArguments[i] = newArgument;
                }
            }

            if (newArguments != null)
            {
                methodCallExpression = methodCallExpression.Update(methodCallExpression.Object, newArguments);
            }

            return(methodCallExpression);
        }
            public override Expression VisitExpression(Expression expression)
            {
                if (expression == null)
                {
                    return(null);
                }

                if (expression.NodeType == ExpressionType.Lambda ||
                    !_partialEvaluationInfo.IsEvaluatableExpression(expression))
                {
                    return(base.VisitExpression(expression));
                }

                var e = expression;

                if (expression.NodeType == ExpressionType.Convert)
                {
                    var unaryExpression = (UnaryExpression)expression;

                    if (unaryExpression.Type.IsNullableType() &&
                        !unaryExpression.Operand.Type.IsNullableType())
                    {
                        e = unaryExpression.Operand;
                    }
                }

                if (e.NodeType != ExpressionType.Constant &&
                    !typeof(IQueryable).GetTypeInfo().IsAssignableFrom(e.Type.GetTypeInfo()))
                {
                    try
                    {
                        string parameterName;

                        var parameterValue = Evaluate(e, out parameterName);

                        var compilerPrefixIndex = parameterName.LastIndexOf(">");
                        if (compilerPrefixIndex != -1)
                        {
                            parameterName = parameterName.Substring(compilerPrefixIndex + 1);
                        }

                        parameterName
                            = string.Format("{0}{1}_{2}",
                                            CompiledQueryParameterPrefix,
                                            parameterName,
                                            _queryContext.ParameterValues.Count);

                        _queryContext.ParameterValues.Add(parameterName, parameterValue);

                        return(Expression.Parameter(expression.Type, parameterName));
                    }
                    catch (Exception exception)
                    {
                        throw new InvalidOperationException(
                                  Strings.ExpressionParameterizationException(expression),
                                  exception);
                    }
                }

                return(expression);
            }