Exemplo n.º 1
0
        /// <summary>
        ///     Visits the given node.
        /// </summary>
        /// <param name="expression"> The expression to visit. </param>
        /// <returns>
        ///     An Expression to the translated input expression.
        /// </returns>
        public override Expression Visit(Expression expression)
        {
            if (_topLevelProjection &&
                (QueryModelVisitor.Expression as MethodCallExpression)?.Method.MethodIsClosedFormOf(
                    QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.GroupByMethod) == true)
            {
                var translation = new GroupByAggregateTranslatingExpressionVisitor(this)
                                  .Translate(expression);

                if (translation != null)
                {
                    QueryModelVisitor.RequiresStreamingGroupResultOperator = false;
                    return(translation);
                }
            }

            _topLevelProjection = false;

            var selectExpression = QueryModelVisitor.TryGetQuery(_querySource);

            if (expression != null &&
                !(expression is ConstantExpression) &&
                !(expression is NewExpression) &&
                !(expression is MemberInitExpression) &&
                selectExpression != null)
            {
                var existingProjectionsCount = selectExpression.Projection.Count;

                var sqlExpression
                    = _sqlTranslatingExpressionVisitorFactory
                      .Create(QueryModelVisitor, selectExpression, inProjection: true)
                      .Visit(expression);

                if (sqlExpression == null)
                {
                    switch (expression)
                    {
                    case MethodCallExpression methodCallExpression when IncludeCompiler.IsIncludeMethod(methodCallExpression):
                        return(base.Visit(expression));

                    case QuerySourceReferenceExpression qsre:
                        if (QueryModelVisitor.ParentQueryModelVisitor != null &&
                            selectExpression.HandlesQuerySource(qsre.ReferencedQuerySource))
                        {
                            selectExpression.ProjectStarTable = selectExpression.GetTableForQuerySource(qsre.ReferencedQuerySource);
                        }
                        break;

                    default:
                        QueryModelVisitor.RequiresClientProjection = true;
                        break;
                    }
                }
                else
                {
                    selectExpression.RemoveRangeFromProjection(existingProjectionsCount);

                    if (!(expression is QuerySourceReferenceExpression))
                    {
                        if (sqlExpression is NullableExpression nullableExpression)
                        {
                            sqlExpression = nullableExpression.Operand;
                        }

                        if (sqlExpression is ColumnExpression)
                        {
                            var index = selectExpression.AddToProjection(sqlExpression);

                            _sourceExpressionProjectionMapping[expression] = selectExpression.Projection[index];

                            return(expression);
                        }
                    }

                    if (!(sqlExpression is ConstantExpression))
                    {
                        var targetExpression
                            = QueryModelVisitor.QueryCompilationContext.QuerySourceMapping
                              .GetExpression(_querySource);

                        if (targetExpression.Type == typeof(ValueBuffer))
                        {
                            var index = selectExpression.AddToProjection(sqlExpression);

                            _sourceExpressionProjectionMapping[expression] = selectExpression.Projection[index];

                            var readValueExpression
                                = _entityMaterializerSource
                                  .CreateReadValueExpression(
                                      targetExpression,
                                      expression.Type.MakeNullable(),
                                      index,
                                      sqlExpression.FindProperty(expression.Type));

                            var outputDataInfo
                                = (expression as SubQueryExpression)?.QueryModel
                                  .GetOutputDataInfo();

                            if (outputDataInfo is StreamedScalarValueInfo)
                            {
                                // Compensate for possible nulls
                                readValueExpression
                                    = Expression.Coalesce(
                                          readValueExpression,
                                          Expression.Default(expression.Type));
                            }

                            return(Expression.Convert(readValueExpression, expression.Type));
                        }

                        return(expression);
                    }
                }
            }

            return(base.Visit(expression));
        }
        /// <summary>
        ///     Visits the given node.
        /// </summary>
        /// <param name="expression"> The expression to visit. </param>
        /// <returns>
        ///     An Expression to the translated input expression.
        /// </returns>
        public override Expression Visit(Expression expression)
        {
            if (_topLevelProjection &&
                (QueryModelVisitor.Expression as MethodCallExpression)?.Method.MethodIsClosedFormOf(
                    QueryModelVisitor.QueryCompilationContext.QueryMethodProvider.GroupByMethod) == true)
            {
                var translation = new GroupByAggregateTranslatingExpressionVisitor(this)

                                  .Translate(expression);

                if (translation != null)
                {
                    QueryModelVisitor.RequiresStreamingGroupResultOperator = false;

                    return(translation);
                }
            }

            _topLevelProjection = false;

            if (expression == null || _selectExpression == null)
            {
                return(expression);
            }

            switch (expression)
            {
            case ConstantExpression constantExpression:
                return(constantExpression);

            // To save mappings so that we can compose afterwards
            case NewExpression newExpression:
                return(VisitNew(newExpression));

            case MemberInitExpression memberInitExpression:
                return(VisitMemberInit(memberInitExpression));

            case QuerySourceReferenceExpression qsre:
                if (_selectExpression.HandlesQuerySource(qsre.ReferencedQuerySource))
                {
                    _selectExpression.ProjectStarTable
                        = _selectExpression.GetTableForQuerySource(qsre.ReferencedQuerySource);
                }

                return(qsre);

            // Skip over Include method
            case MethodCallExpression methodCallExpression when IncludeCompiler.IsIncludeMethod(methodCallExpression):
                return(methodCallExpression);

            default:
                var sqlExpression
                    = _sqlTranslatingExpressionVisitorFactory
                      .Create(QueryModelVisitor, _selectExpression, inProjection: true)
                      .Visit(expression);

                if (sqlExpression == null)
                {
                    QueryModelVisitor.RequiresClientProjection = true;

                    return(base.Visit(expression));
                }
                else if (sqlExpression is ConstantExpression)
                {
                    return(base.Visit(expression));
                }
                else
                {
                    if (sqlExpression is NullableExpression nullableExpression)
                    {
                        sqlExpression = nullableExpression.Operand;
                    }

                    if (sqlExpression is ColumnExpression)
                    {
                        var index = _selectExpression.AddToProjection(sqlExpression);

                        _sourceExpressionProjectionMapping[expression] = _selectExpression.Projection[index];

                        return(expression);
                    }

                    var targetExpression
                        = QueryModelVisitor.QueryCompilationContext.QuerySourceMapping
                          .GetExpression(_querySource);

                    if (targetExpression.Type == typeof(ValueBuffer))
                    {
                        var index = _selectExpression.AddToProjection(sqlExpression);

                        _sourceExpressionProjectionMapping[expression] = _selectExpression.Projection[index];

                        var readValueExpression
                            = _entityMaterializerSource
                              .CreateReadValueExpression(
                                  targetExpression,
                                  expression.Type.MakeNullable(),
                                  index,
                                  sqlExpression.FindProperty(expression.Type));

                        var outputDataInfo
                            = (expression as SubQueryExpression)?.QueryModel
                              .GetOutputDataInfo();

                        if (outputDataInfo is StreamedScalarValueInfo)
                        {
                            // Compensate for possible nulls
                            readValueExpression
                                = Expression.Coalesce(
                                      readValueExpression,
                                      Expression.Default(expression.Type));
                        }

                        return(Expression.Convert(readValueExpression, expression.Type));
                    }

                    return(expression);
                }
            }
        }