Пример #1
0
        public static DQueryable <T> SelectMany <T>(this DQueryable <T> query, CollectionElementToken cet)
        {
            Type elementType = cet.Parent.Type.ElementType();

            var collectionSelector = Expression.Lambda(typeof(Func <,>).MakeGenericType(typeof(object), typeof(IEnumerable <>).MakeGenericType(elementType)),
                                                       Expression.Call(miDefaultIfEmptyE.MakeGenericMethod(elementType),
                                                                       cet.Parent.BuildExpression(query.Context)),
                                                       query.Context.Parameter);

            var elementParameter = cet.CreateParameter();

            var properties = query.Context.Replacemens.Values.And(cet.CreateExpression(elementParameter));

            var ctor = TupleReflection.TupleChainConstructor(properties);

            var resultSelector = Expression.Lambda(Expression.Convert(ctor, typeof(object)), query.Context.Parameter, elementParameter);

            var resultQuery = query.Query.Provider.CreateQuery <object>(Expression.Call(null, miSelectMany.MakeGenericMethod(typeof(object), elementType, typeof(object)),
                                                                                        new Expression[] { query.Query.Expression, Expression.Quote(collectionSelector), Expression.Quote(resultSelector) }));

            var parameter = Expression.Parameter(typeof(object));

            var newReplacements = query.Context.Replacemens.Keys.And(cet).Select((a, i) => new
            {
                Token      = a,
                Expression = TupleReflection.TupleChainProperty(Expression.Convert(parameter, ctor.Type), i)
            }).ToDictionary(a => a.Token, a => a.Expression);

            return(new DQueryable <T>(resultQuery,
                                      new BuildExpressionContext(ctor.Type, parameter, newReplacements)));
        }
Пример #2
0
        static LambdaExpression KeySelector(BuildExpressionContext context, HashSet <QueryToken> keyTokens)
        {
            var keySelector = Expression.Lambda(
                TupleReflection.TupleChainConstructor(keyTokens.Select(t => t.BuildExpression(context)).ToList()),
                context.Parameter);

            return(keySelector);
        }
Пример #3
0
        internal Func <FieldReader, object> GetRowReader()
        {
            ParameterExpression reader = Expression.Parameter(typeof(FieldReader));

            var tupleConstructor = TupleReflection.TupleChainConstructor(
                table.Columns.Values.Select((c, i) => FieldReader.GetExpression(reader, i, GetColumnType(c)))
                );

            return(Expression.Lambda <Func <FieldReader, object> >(tupleConstructor, reader).Compile());
        }
Пример #4
0
        static Expression <Func <object, object> > TupleConstructor(BuildExpressionContext context, HashSet <QueryToken> tokens, out BuildExpressionContext newContext)
        {
            string str = tokens.Select(t => QueryUtils.CanColumn(t)).NotNull().ToString("\r\n");

            if (str == null)
            {
                throw new ApplicationException(str);
            }

            List <Expression> expressions = tokens.Select(t => t.BuildExpression(context)).ToList();
            Expression        ctor        = TupleReflection.TupleChainConstructor(expressions);

            var pe = Expression.Parameter(typeof(object));

            newContext = new BuildExpressionContext(
                ctor.Type, pe,
                tokens.Select((t, i) => new { Token = t, Expr = TupleReflection.TupleChainProperty(Expression.Convert(pe, ctor.Type), i) }).ToDictionary(t => t.Token, t => t.Expr));

            return(Expression.Lambda <Func <object, object> >(
                       (Expression)Expression.Convert(ctor, typeof(object)), context.Parameter));
        }
Пример #5
0
        static LambdaExpression ResultSelectSelectorAndContext(BuildExpressionContext context, HashSet <QueryToken> keyTokens, HashSet <AggregateToken> aggregateTokens, Type keyTupleType, out BuildExpressionContext newContext)
        {
            Dictionary <QueryToken, Expression> resultExpressions = new Dictionary <QueryToken, Expression>();
            ParameterExpression pk = Expression.Parameter(keyTupleType, "key");

            resultExpressions.AddRange(keyTokens.Select((kt, i) => KVP.Create(kt,
                                                                              TupleReflection.TupleChainProperty(pk, i))));

            ParameterExpression pe = Expression.Parameter(typeof(IEnumerable <object>), "e");

            resultExpressions.AddRange(aggregateTokens.Select(at => KVP.Create((QueryToken)at,
                                                                               BuildAggregateExpression(pe, at, context))));

            var resultConstructor = TupleReflection.TupleChainConstructor(resultExpressions.Values);

            ParameterExpression pg = Expression.Parameter(typeof(object), "gr");

            newContext = new BuildExpressionContext(resultConstructor.Type, pg,
                                                    resultExpressions.Keys.Select((t, i) => KVP.Create(t, TupleReflection.TupleChainProperty(Expression.Convert(pg, resultConstructor.Type), i))).ToDictionary());

            return(Expression.Lambda(Expression.Convert(resultConstructor, typeof(object)), pk, pe));
        }
        protected internal override Expression VisitProjection(ProjectionExpression proj)
        {
            if (currentSource == null)
            {
                currentSource = WithoutOrder(proj.Select);

                Expression projector = this.Visit(proj.Projector);

                if (projector != proj.Projector)
                {
                    proj = new ProjectionExpression(proj.Select, projector, proj.UniqueFunction, proj.Type);
                }

                currentSource = null;
                return(proj);
            }
            else
            {
                HashSet <ColumnExpression> columns = ExternalColumnGatherer.Gatherer(proj, currentSource.Alias);

                if (columns.Count == 0)
                {
                    Expression projector = Visit(proj.Projector);

                    ConstantExpression key   = Expression.Constant(0);
                    Type            kvpType  = typeof(KeyValuePair <,>).MakeGenericType(key.Type, projector.Type);
                    ConstructorInfo ciKVP    = kvpType.GetConstructor(new[] { key.Type, projector.Type });
                    Type            projType = proj.UniqueFunction == null ? typeof(IEnumerable <>).MakeGenericType(kvpType) : kvpType;

                    var childProj = new ProjectionExpression(proj.Select,
                                                             Expression.New(ciKVP, key, projector), proj.UniqueFunction, projType);

                    return(new ChildProjectionExpression(childProj,
                                                         Expression.Constant(0), inMList != null, inMList ?? proj.Type, new LookupToken()));
                }
                else
                {
                    SelectExpression external;
                    IEnumerable <ColumnExpression> externalColumns;

                    if (!IsKey(currentSource, columns))
                    {
                        Alias           aliasDistinct     = aliasGenerator.GetUniqueAlias(currentSource.Alias.Name + "D");
                        ColumnGenerator generatorDistinct = new ColumnGenerator();

                        List <ColumnDeclaration> columnDistinct = columns.Select(ce => generatorDistinct.MapColumn(ce)).ToList();
                        external = new SelectExpression(aliasDistinct, true, null, columnDistinct, currentSource, null, null, null, 0);


                        Dictionary <ColumnExpression, ColumnExpression> distinctReplacements = columnDistinct.ToDictionary(
                            cd => (ColumnExpression)cd.Expression,
                            cd => cd.GetReference(aliasDistinct));

                        proj = (ProjectionExpression)ColumnReplacer.Replace(proj, distinctReplacements);

                        externalColumns = distinctReplacements.Values.ToHashSet();
                    }
                    else
                    {
                        external        = currentSource;
                        externalColumns = columns;
                    }

                    ColumnGenerator          generatorSM       = new ColumnGenerator();
                    List <ColumnDeclaration> columnsSMExternal = externalColumns.Select(ce => generatorSM.MapColumn(ce)).ToList();
                    List <ColumnDeclaration> columnsSMInternal = proj.Select.Columns.Select(cd => generatorSM.MapColumn(cd.GetReference(proj.Select.Alias))).ToList();

                    List <OrderExpression> innerOrders;
                    SelectExpression       @internal = ExtractOrders(proj.Select, out innerOrders);

                    Alias            aliasSM    = aliasGenerator.GetUniqueAlias(@internal.Alias.Name + "SM");
                    SelectExpression selectMany = new SelectExpression(aliasSM, false, null, columnsSMExternal.Concat(columnsSMInternal),
                                                                       new JoinExpression(JoinType.CrossApply,
                                                                                          external,
                                                                                          @internal, null), null, innerOrders, null, 0);

                    SelectExpression old = currentSource;
                    currentSource = WithoutOrder(selectMany);

                    var selectManyReplacements = selectMany.Columns.ToDictionary(
                        cd => (ColumnExpression)cd.Expression,
                        cd => cd.GetReference(aliasSM));

                    Expression projector = ColumnReplacer.Replace(proj.Projector, selectManyReplacements);

                    projector = Visit(projector);

                    currentSource = old;

                    Expression      key      = TupleReflection.TupleChainConstructor(columnsSMExternal.Select(cd => cd.GetReference(aliasSM).Nullify()));
                    Type            kvpType  = typeof(KeyValuePair <,>).MakeGenericType(key.Type, projector.Type);
                    ConstructorInfo ciKVP    = kvpType.GetConstructor(new[] { key.Type, projector.Type });
                    Type            projType = proj.UniqueFunction == null ? typeof(IEnumerable <>).MakeGenericType(kvpType) : kvpType;

                    var childProj = new ProjectionExpression(selectMany,
                                                             Expression.New(ciKVP, key, projector), proj.UniqueFunction, projType);

                    return(new ChildProjectionExpression(childProj,
                                                         TupleReflection.TupleChainConstructor(columns.Select(a => a.Nullify())), inMList != null, inMList ?? proj.Type, new LookupToken()));
                }
            }
        }