protected ClientJoinExpression UpdateClientJoin(ClientJoinExpression join, ProjectionExpression projection, IEnumerable<Expression> outerKey, IEnumerable<Expression> innerKey)
 {
     if (projection != join.Projection || outerKey != join.OuterKey || innerKey != join.InnerKey)
     {
         return new ClientJoinExpression(projection, outerKey, innerKey);
     }
     return join;
 }
Exemple #2
0
 protected override Expression VisitClientJoin(ClientJoinExpression join)
 {
     var innerKey = this.VisitExpressionList(join.InnerKey);
     var outerKey = this.VisitExpressionList(join.OuterKey);
     ProjectionExpression projection = (ProjectionExpression)this.Visit(join.Projection);
     if (projection != join.Projection || innerKey != join.InnerKey || outerKey != join.OuterKey) {
         return new ClientJoinExpression(projection, outerKey, innerKey);
     }
     return join;
 }
        protected override Expression VisitClientJoin(ClientJoinExpression join)
        {
            var innerKey = this.VisitExpressionList(join.InnerKey);
            var outerKey = this.VisitExpressionList(join.OuterKey);
            ProjectionExpression projection = (ProjectionExpression)this.Visit(join.Projection);

            if (projection != join.Projection || innerKey != join.InnerKey || outerKey != join.OuterKey)
            {
                return(new ClientJoinExpression(projection, outerKey, innerKey));
            }
            return(join);
        }
 protected override Expression VisitClientJoin(ClientJoinExpression join)
 {
     // treat client joins as new top level
     var saveTop = isTopLevel;
     var saveSelect = currentSelect;
     isTopLevel = true;
     currentSelect = null;
     Expression result = base.VisitClientJoin(join);
     isTopLevel = saveTop;
     currentSelect = saveSelect;
     return result;
 }
        /// <summary>
        ///
        /// </summary>
        /// <param name="join"></param>
        /// <returns></returns>
        protected override Expression VisitClientJoin(ClientJoinExpression join)
        {
            // convert client join into a up-front lookup table builder & replace client-join in tree with lookup accessor

            // 1) lookup = query.Select(e => new KVP(key: inner, value: e)).ToLookup(kvp => kvp.Key, kvp => kvp.Value)
            Expression innerKey = MakeJoinKey(join.InnerKey);
            Expression outerKey = MakeJoinKey(join.OuterKey);

            ConstructorInfo      kvpConstructor  = typeof(KeyValuePair <,>).MakeGenericType(innerKey.Type, join.Projection.Projector.Type).GetConstructor(new Type[] { innerKey.Type, join.Projection.Projector.Type });
            Expression           constructKVPair = Expression.New(kvpConstructor, innerKey, join.Projection.Projector);
            ProjectionExpression newProjection   = new ProjectionExpression(join.Projection.Source, constructKVPair);

            int        iLookup   = ++nLookup;
            Expression execution = this.ExecuteProjection(newProjection, false);

            ParameterExpression kvp = Expression.Parameter(constructKVPair.Type, "kvp");

            // filter out nulls
            if (join.Projection.Projector.NodeType == (ExpressionType)DbExpressionType.OuterJoined)
            {
                LambdaExpression pred = Expression.Lambda(
                    Expression.NotEqual(
                        Expression.PropertyOrField(kvp, "Value"),
                        Expression.Constant(null, join.Projection.Projector.Type)
                        ),
                    kvp
                    );
                execution = Expression.Call(typeof(Enumerable), "Where", new Type[] { kvp.Type }, execution, pred);
            }

            // make lookup
            LambdaExpression keySelector     = Expression.Lambda(Expression.PropertyOrField(kvp, "Key"), kvp);
            LambdaExpression elementSelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Value"), kvp);
            Expression       toLookup        = Expression.Call(typeof(Enumerable), "ToLookup", new Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector);

            // 2) agg(lookup[outer])
            ParameterExpression lookup   = Expression.Parameter(toLookup.Type, "lookup" + iLookup);
            PropertyInfo        property = lookup.Type.GetProperty("Item");
            Expression          access   = Expression.Call(lookup, property.GetGetMethod(), this.Visit(outerKey));

            if (join.Projection.Aggregator != null)
            {
                // apply aggregator
                access = DbExpressionReplacer.Replace(join.Projection.Aggregator.Body, join.Projection.Aggregator.Parameters[0], access);
            }

            this.variables.Add(lookup);
            this.initializers.Add(toLookup);

            return(access);
        }
Exemple #6
0
        protected override Expression VisitClientJoin(ClientJoinExpression join)
        {
            // treat client joins as new top level
            var saveTop    = isTopLevel;
            var saveSelect = currentSelect;

            isTopLevel    = true;
            currentSelect = null;
            Expression result = base.VisitClientJoin(join);

            isTopLevel    = saveTop;
            currentSelect = saveSelect;
            return(result);
        }
        protected override Expression VisitClientJoin(ClientJoinExpression join)
        {
            // convert client join into a up-front lookup table builder & replace client-join in tree with lookup accessor

            // 1) lookup = query.Select(e => new KVP(key: inner, value: e)).ToLookup(kvp => kvp.Key, kvp => kvp.Value)
            Expression innerKey = MakeJoinKey(join.InnerKey);
            Expression outerKey = MakeJoinKey(join.OuterKey);

            ConstructorInfo kvpConstructor = typeof(KeyValuePair<,>).MakeGenericType(innerKey.Type, join.Projection.Projector.Type).GetConstructor(new System.Type[] { innerKey.Type, join.Projection.Projector.Type });
            Expression constructKVPair = Expression.New(kvpConstructor, innerKey, join.Projection.Projector);
            ProjectionExpression newProjection = new ProjectionExpression(join.Projection.Source, constructKVPair);

            int iLookup = ++nLookup;
            Expression execution = ExecuteProjection(newProjection, false);

            ParameterExpression kvp = Expression.Parameter(constructKVPair.Type, "kvp");

            // filter out nulls
            if (join.Projection.Projector.NodeType == (ExpressionType)DbExpressionType.OuterJoined)
            {
                LambdaExpression pred = Expression.Lambda(
                    Expression.NotEqual(
                        Expression.PropertyOrField(kvp, "Value"),
                        Expression.Constant(null, join.Projection.Projector.Type)
                        ),
                    kvp
                    );
                execution = Expression.Call(typeof(Enumerable), "Where", new System.Type[] { kvp.Type }, execution, pred);
            }

            // make lookup
            LambdaExpression keySelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Key"), kvp);
            LambdaExpression elementSelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Value"), kvp);
            Expression toLookup = Expression.Call(typeof(Enumerable), "ToLookup", new System.Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector);

            // 2) agg(lookup[outer])
            ParameterExpression lookup = Expression.Parameter(toLookup.Type, "lookup" + iLookup);
            PropertyInfo property = lookup.Type.GetProperty("Item");
            Expression access = Expression.Call(lookup, property.GetGetMethod(), Visit(outerKey));
            if (join.Projection.Aggregator != null)
            {
                // apply aggregator
                access = DbExpressionReplacer.Replace(join.Projection.Aggregator.Body, join.Projection.Aggregator.Parameters[0], access);
            }

            variables.Add(lookup);
            initializers.Add(toLookup);

            return access;
        }
        protected override Expression VisitClientJoin(ClientJoinExpression join)
        {
            // convert client join into a up-front lookup table builder & replace client-join in tree with lookup accessor

            // 1) lookup = query.Select(e => new KVP(key: inner, value: e)).ToLookup(kvp => kvp.Key, kvp => kvp.Value)
            Expression innerKey = MakeJoinKey(join.InnerKey);
            Expression outerKey = MakeJoinKey(join.OuterKey);

            var                  kvpConstructor  = ReflectionCache.GetMember("KeyValueConstructor", new[] { innerKey.Type, join.Projection.Projector.Type }, pars => typeof(KeyValuePair <,>).MakeGenericType(pars).GetConstructor(pars));
            Expression           constructKVPair = Expression.New(kvpConstructor, innerKey, join.Projection.Projector);
            ProjectionExpression newProjection   = new ProjectionExpression(join.Projection.Select, constructKVPair, _isAsync, join.Projection.IsNoTracking);

            int        iLookup   = ++_lookup;
            Expression execution = ExecuteProjection(newProjection, false);

            ParameterExpression kvp = Expression.Parameter(constructKVPair.Type, "kvp");

            // filter out nulls
            if (join.Projection.Projector.NodeType == (ExpressionType)DbExpressionType.OuterJoined)
            {
                var nullType = ReflectionCache.GetMember("NullableType", join.Projection.Projector.Type, k => k.GetNullableType());
                var pred     = Expression.Lambda(
                    Expression.PropertyOrField(kvp, "Value").NotEqual(Expression.Constant(null, nullType)),
                    kvp
                    );
                execution = Expression.Call(typeof(Enumerable), nameof(Enumerable.Where), new Type[] { kvp.Type }, execution, pred);
            }

            // make lookup
            var keySelector     = Expression.Lambda(Expression.PropertyOrField(kvp, "Key"), kvp);
            var elementSelector = Expression.Lambda(Expression.PropertyOrField(kvp, "Value"), kvp);
            var toLookup        = Expression.Call(typeof(Enumerable), nameof(Enumerable.ToLookup), new Type[] { kvp.Type, outerKey.Type, join.Projection.Projector.Type }, execution, keySelector, elementSelector);

            // 2) agg(lookup[outer])
            var        lookup   = Expression.Parameter(toLookup.Type, $"lookup{iLookup}");
            var        property = lookup.Type.GetProperty("Item");
            Expression access   = Expression.Call(lookup, property.GetGetMethod(), Visit(outerKey));

            if (join.Projection.Aggregator != null)
            {
                // apply aggregator
                access = DbExpressionReplacer.Replace(join.Projection.Aggregator.Body, join.Projection.Aggregator.Parameters[0], access);
            }

            _variables.Add(lookup);
            _initializers.Add(toLookup);

            return(access);
        }
Exemple #9
0
 protected virtual Expression VisitClientJoin(ClientJoinExpression join)
 {
     this.AddAlias(join.Projection.Select.Alias);
     this.Write("ClientJoin(");
     this.WriteLine(Indentation.Inner);
     this.Write("OuterKey(");
     this.VisitExpressionList(join.OuterKey);
     this.Write("),");
     this.WriteLine(Indentation.Same);
     this.Write("InnerKey(");
     this.VisitExpressionList(join.InnerKey);
     this.Write("),");
     this.WriteLine(Indentation.Same);
     this.Visit(join.Projection);
     this.WriteLine(Indentation.Outer);
     this.Write(")");
     return join;
 }
 protected virtual Expression VisitClientJoin(ClientJoinExpression join)
 {
     var projection = (ProjectionExpression)this.Visit(join.Projection);
     var outerKey = this.VisitExpressionList(join.OuterKey);
     var innerKey = this.VisitExpressionList(join.InnerKey);
     return this.UpdateClientJoin(join, projection, outerKey, innerKey);
 }