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))); }
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); }
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()); }
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)); }
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())); } } }