Пример #1
0
        private Expression BindFirst(Expression source, LambdaExpression predicate, string kind, bool isRoot)
        {
            ProjectionExpression projection = VisitSequence(source);

            Expression where = null;
            if (predicate != null)
            {
                map[predicate.Parameters[0]] = projection.Projector;
                where = Visit(predicate.Body);
            }
            Expression take = kind.StartsWith("First") ? Expression.Constant(1) : null;

            if (take != null || where != null)
            {
                var alias           = GetNextAlias();
                ProjectedColumns pc = ProjectColumns(projection.Projector, alias, projection.Source.Alias);
                projection = new ProjectionExpression(
                    new SelectExpression(alias, pc.Columns, projection.Source, where, null, null, false, null, take),
                    pc.Projector
                    );
            }
            if (isRoot)
            {
                Type elementType          = projection.Projector.Type;
                ParameterExpression p     = Expression.Parameter(typeof(IEnumerable <>).MakeGenericType(elementType), "p");
                LambdaExpression    gator =
                    Expression.Lambda(Expression.Call(typeof(Enumerable), kind, new[] { elementType }, p), p);
                return(new ProjectionExpression(projection.Source, projection.Projector, gator));
            }
            return(projection);
        }
Пример #2
0
        protected virtual Expression BindOrderBy(Type resultType, Expression source, LambdaExpression orderSelector,
                                                 OrderType orderType)
        {
            List <OrderExpression> myThenBys = thenBys;

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

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

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

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

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

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

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

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

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

            return(new ProjectionExpression(
                       new SelectExpression(alias, pc.Columns, join, null),
                       pc.Projector
                       ));
        }
Пример #4
0
        private Expression BindDistinct(Expression source)
        {
            ProjectionExpression projection = VisitSequence(source);
            SelectExpression     select     = projection.Source;
            var alias           = GetNextAlias();
            ProjectedColumns pc = ProjectColumns(projection.Projector, alias, projection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(alias, pc.Columns, projection.Source, null, null, null, true, null, null),
                       pc.Projector
                       ));
        }
Пример #5
0
        private Expression BindSkip(Expression source, Expression skip)
        {
            ProjectionExpression projection = VisitSequence(source);

            skip = Visit(skip);
            SelectExpression select = projection.Source;
            var alias           = GetNextAlias();
            ProjectedColumns pc = ProjectColumns(projection.Projector, alias, projection.Source.Alias);

            return(new ProjectionExpression(
                       new SelectExpression(alias, pc.Columns, projection.Source, null, null, null, false, skip, null),
                       pc.Projector
                       ));
        }
Пример #6
0
        private Expression BindSelect(Type resultType, Expression source, LambdaExpression selector)
        {
            ProjectionExpression projection = VisitSequence(source);

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

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

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

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

            map[keySelector.Parameters[0]] = projection.Projector;
            Expression keyExpr = Visit(keySelector.Body);

            Expression elemExpr = projection.Projector;

            if (elementSelector != null)
            {
                map[elementSelector.Parameters[0]] = projection.Projector;
                elemExpr = Visit(elementSelector.Body);
            }

            // Use ProjectColumns to get group-by expressions from key expression
            ProjectedColumns         keyProjection = 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 = VisitSequence(source);

            // recompute key columns for group expressions relative to subquery (need these for doing the correlation predicate)
            map[keySelector.Parameters[0]] = subqueryBasis.Projector;
            Expression subqueryKey = Visit(keySelector.Body);

            // use same projection trick to get group-by expressions based on subquery
            ProjectedColumns subqueryKeyPC = ProjectColumns(subqueryKey, subqueryBasis.Source.Alias,
                                                            subqueryBasis.Source.Alias);
            IEnumerable <Expression> subqueryGroupExprs = subqueryKeyPC.Columns.Select(c => c.Expression);
            Expression subqueryCorrelation = BuildPredicateWithNullsEqual(subqueryGroupExprs, groupExprs);

            // compute element based on duplicated subquery
            Expression subqueryElemExpr = subqueryBasis.Projector;

            if (elementSelector != null)
            {
                map[elementSelector.Parameters[0]] = subqueryBasis.Projector;
                subqueryElemExpr = Visit(elementSelector.Body);
            }

            // build subquery that projects the desired element
            var elementAlias = GetNextAlias();
            ProjectedColumns     elementPC       = ProjectColumns(subqueryElemExpr, elementAlias, subqueryBasis.Source.Alias);
            ProjectionExpression elementSubquery =
                new ProjectionExpression(
                    new SelectExpression(elementAlias, elementPC.Columns, subqueryBasis.Source, subqueryCorrelation),
                    elementPC.Projector
                    );

            var alias = GetNextAlias();

            // make it possible to tie aggregates back to this group-by
            GroupByInfo info = new GroupByInfo(alias, elemExpr);

            groupByMap.Add(elementSubquery, info);

            Expression resultExpr;

            if (resultSelector != null)
            {
                Expression saveGroupElement = currentGroupElement;
                currentGroupElement = elementSubquery;
                // compute result expression based on key and element-subquery
                map[resultSelector.Parameters[0]] = keyProjection.Projector;
                map[resultSelector.Parameters[1]] = elementSubquery;
                resultExpr          = Visit(resultSelector.Body);
                currentGroupElement = saveGroupElement;
            }
            else
            {
                // result must be IGrouping<K,E>
                resultExpr =
                    Expression.New(
                        typeof(Grouping <,>).MakeGenericType(keyExpr.Type, subqueryElemExpr.Type).GetConstructors()[0],
                        new[] { keyExpr, elementSubquery }
                        );
            }

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

            // make it possible to tie aggregates back to this group-by
            Expression projectedElementSubquery = ((NewExpression)pc.Projector).Arguments[1];

            groupByMap.Add(projectedElementSubquery, info);

            return(new ProjectionExpression(
                       new SelectExpression(alias, pc.Columns, projection.Source, null, null, groupExprs),
                       pc.Projector
                       ));
        }