Пример #1
0
        protected virtual Expression BindOrderBy(Type resultType, Expression source, LambdaExpression orderSelector, OrderType orderType)
        {
            List <OrderExpression> myThenBys = this.thenBys;

            this.thenBys = null;
            ProjectionExpression projection = this.VisitSequence(source);

            this.map[orderSelector.Parameters[0]] = projection.Projector;
            List <OrderExpression> orderings = new List <OrderExpression>();

            orderings.Add(new OrderExpression(orderType, this.Visit(orderSelector.Body)));

            if (myThenBys != null)
            {
                for (int i = myThenBys.Count - 1; i >= 0; i--)
                {
                    OrderExpression  tb     = myThenBys[i];
                    LambdaExpression lambda = (LambdaExpression)tb.Expression;
                    this.map[lambda.Parameters[0]] = projection.Projector;
                    orderings.Add(new OrderExpression(tb.OrderType, this.Visit(lambda.Body)));
                }
            }

            string           alias = this.GetNextAlias();
            ProjectedColumns pc    = this.ProjectColumns(projection.Projector, alias, projection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(resultType, alias, pc.Columns, projection.Source, null, orderings.AsReadOnly(), null),
                       pc.Projector
                       ));
        }
Пример #2
0
        private Expression BindSelect(Type resultType, Expression source, LambdaExpression selector)
        {
            ProjectionExpression projection = (ProjectionExpression)this.Visit(source);

            this.map[selector.Parameters[0]] = projection.Projector;
            Expression       expression = this.Visit(selector.Body);
            string           alias      = this.GetNextAlias();
            ProjectedColumns pc         = this.ProjectColumns(expression, alias, projection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(resultType, alias, pc.Columns, projection.Source, null),
                       pc.Projector
                       ));
        }
Пример #3
0
        private Expression BindWhere(Type resultType, Expression source, LambdaExpression predicate)
        {
            ProjectionExpression projection = (ProjectionExpression)this.Visit(source);

            this.map[predicate.Parameters[0]] = projection.Projector;
            Expression where = this.Visit(predicate.Body);
            string           alias = this.GetNextAlias();
            ProjectedColumns pc    = this.ProjectColumns(projection.Projector, alias, projection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(resultType, alias, pc.Columns, projection.Source, where),
                       pc.Projector
                       ));
        }
Пример #4
0
        protected virtual Expression BindJoin(Type resultType, Expression outerSource, Expression innerSource, LambdaExpression outerKey, LambdaExpression innerKey, LambdaExpression resultSelector)
        {
            ProjectionExpression outerProjection = (ProjectionExpression)this.Visit(outerSource);
            ProjectionExpression innerProjection = (ProjectionExpression)this.Visit(innerSource);

            this.map[outerKey.Parameters[0]] = outerProjection.Projector;
            Expression outerKeyExpr = this.Visit(outerKey.Body);

            this.map[innerKey.Parameters[0]] = innerProjection.Projector;
            Expression innerKeyExpr = this.Visit(innerKey.Body);

            this.map[resultSelector.Parameters[0]] = outerProjection.Projector;
            this.map[resultSelector.Parameters[1]] = innerProjection.Projector;
            Expression       resultExpr = this.Visit(resultSelector.Body);
            JoinExpression   join       = new JoinExpression(resultType, JoinType.InnerJoin, outerProjection.Source, innerProjection.Source, Expression.Equal(outerKeyExpr, innerKeyExpr));
            string           alias      = this.GetNextAlias();
            ProjectedColumns pc         = this.ProjectColumns(resultExpr, alias, outerProjection.Source.Alias, innerProjection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(resultType, alias, pc.Columns, join, null),
                       pc.Projector
                       ));
        }
Пример #5
0
        protected virtual Expression BindGroupBy(Expression source, LambdaExpression keySelector, LambdaExpression elementSelector, LambdaExpression resultSelector)
        {
            ProjectionExpression projection = this.VisitSequence(source);



            this.map[keySelector.Parameters[0]] = projection.Projector;

            Expression keyExpr = this.Visit(keySelector.Body);

            Expression elemExpr = projection.Projector;

            if (elementSelector != null)
            {
                this.map[elementSelector.Parameters[0]] = projection.Projector;

                elemExpr = this.Visit(elementSelector.Body);
            }



            // Use ProjectColumns to get group-by expressions from key expression

            ProjectedColumns keyProjection = this.ProjectColumns(keyExpr, projection.Source.Alias, projection.Source.Alias);

            IEnumerable <Expression> groupExprs = keyProjection.Columns.Select(c => c.Expression);

            // make duplicate of source query as basis of element subquery by visiting the source again

            ProjectionExpression subqueryBasis = this.VisitSequence(source);

            // recompute key columns for group expressions relative to subquery (need these for doing the correlation predicate)

            this.map[keySelector.Parameters[0]] = subqueryBasis.Projector;

            Expression subqueryKey = this.Visit(keySelector.Body);



            // use same projection trick to get group-by expressions based on subquery

            ProjectedColumns subqueryKeyPC = this.ProjectColumns(subqueryKey, subqueryBasis.Source.Alias, subqueryBasis.Source.Alias);

            IEnumerable <Expression> subqueryGroupExprs = subqueryKeyPC.Columns.Select(c => c.Expression);

            Expression subqueryCorrelation = this.BuildPredicateWithNullsEqual(subqueryGroupExprs, groupExprs);



            // compute element based on duplicated subquery

            Expression subqueryElemExpr = subqueryBasis.Projector;

            if (elementSelector != null)
            {
                this.map[elementSelector.Parameters[0]] = subqueryBasis.Projector;

                subqueryElemExpr = this.Visit(elementSelector.Body);
            }



            // build subquery that projects the desired element

            string elementAlias = this.GetNextAlias();

            ProjectedColumns elementPC = this.ProjectColumns(subqueryElemExpr, elementAlias, subqueryBasis.Source.Alias);

            ProjectionExpression elementSubquery =

                new ProjectionExpression(

                    new SelectExpression(TypeSystem.GetSequenceType(subqueryElemExpr.Type), elementAlias, elementPC.Columns, subqueryBasis.Source, subqueryCorrelation),

                    elementPC.Projector

                    );

            string alias = this.GetNextAlias();

            // make it possible to tie aggregates back to this group-by

            GroupByInfo info = new GroupByInfo(alias, elemExpr);

            this.groupByMap.Add(elementSubquery, info);

            Expression resultExpr;

            if (resultSelector != null)
            {
                Expression saveGroupElement = this.currentGroupElement;

                this.currentGroupElement = elementSubquery;

                // compute result expression based on key & element-subquery

                this.map[resultSelector.Parameters[0]] = keyProjection.Projector;

                this.map[resultSelector.Parameters[1]] = elementSubquery;

                resultExpr = this.Visit(resultSelector.Body);

                this.currentGroupElement = saveGroupElement;
            }

            else
            {
                // result must be IGrouping<K,E>

                resultExpr = Expression.New(

                    typeof(Grouping <,>).MakeGenericType(keyExpr.Type, subqueryElemExpr.Type).GetConstructors()[0],

                    new Expression[] { keyExpr, elementSubquery }

                    );
            }

            ProjectedColumns pc = this.ProjectColumns(resultExpr, alias, projection.Source.Alias);

            // make it possible to tie aggregates back to this group-by

            Expression projectedElementSubquery = ((NewExpression)pc.Projector).Arguments[1];

            this.groupByMap.Add(projectedElementSubquery, info);

            return(new ProjectionExpression(

                       new SelectExpression(TypeSystem.GetSequenceType(resultExpr.Type), alias, pc.Columns, projection.Source, null, null, groupExprs),

                       pc.Projector

                       ));
        }