Exemplo n.º 1
0
        protected override void FlattenSubQuery(
            [NotNull] SubQueryExpression subQueryExpression,
            [NotNull] FromClauseBase fromClause,
            [NotNull] QueryModel queryModel,
            int destinationIndex)
        {
            Check.NotNull(subQueryExpression, nameof(subQueryExpression));
            Check.NotNull(fromClause, nameof(fromClause));
            Check.NotNull(queryModel, nameof(queryModel));

            var subQueryModel = subQueryExpression.QueryModel;

            VisitQueryModel(subQueryModel);

            if ((subQueryModel.ResultOperators
                 .All(ro => (ro is OfTypeResultOperator || ro is CastResultOperator)) &&
                 !subQueryModel.BodyClauses.Any(bc => bc is OrderByClause)) ||
                (queryModel.IsIdentityQuery() &&
                 !queryModel.ResultOperators.Any()))
            {
                var innerMainFromClause = subQueryExpression.QueryModel.MainFromClause;

                var isGeneratedNameOuter = fromClause.HasGeneratedItemName();
                var outerItemName        = fromClause.ItemName;
                CopyFromClauseData(innerMainFromClause, fromClause);

                if (innerMainFromClause.HasGeneratedItemName() &&
                    !isGeneratedNameOuter)
                {
                    fromClause.ItemName = outerItemName;
                }

                var innerSelectorMapping = new QuerySourceMapping();

                innerSelectorMapping.AddMapping(fromClause, subQueryExpression.QueryModel.SelectClause.Selector);

                queryModel.TransformExpressions(
                    ex => ReferenceReplacingExpressionVisitor
                    .ReplaceClauseReferences(ex, innerSelectorMapping, false));

                InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);

                foreach (var resultOperator in subQueryModel.ResultOperators.Reverse())
                {
                    queryModel.ResultOperators.Insert(0, resultOperator);
                }

                var innerBodyClauseMapping = new QuerySourceMapping();

                innerBodyClauseMapping
                .AddMapping(innerMainFromClause, new QuerySourceReferenceExpression(fromClause));

                queryModel.TransformExpressions(ex =>
                                                ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(ex, innerBodyClauseMapping, false));

                foreach (var queryAnnotation
                         in _queryAnnotations
                         .Where(qa => qa.QuerySource == subQueryExpression.QueryModel.MainFromClause))
                {
                    queryAnnotation.QuerySource = fromClause;
                    queryAnnotation.QueryModel  = queryModel;
                }
            }
        }