예제 #1
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Value"));
 }
예제 #2
0
 protected override SequenceConvertInfo Convert(
     ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
예제 #3
0
 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
 {
     return(methodCall.IsQueryable("Insert", "InsertWithIdentity"));
 }
예제 #4
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            var isSubQuery = sequence.SelectQuery.Select.IsDistinct;

            if (isSubQuery)
            {
                sequence = new SubQueryContext(sequence);
            }

            switch (methodCall.Arguments.Count)
            {
            case 1:
                // static int Insert<T>              (this IValueInsertable<T> source)
                // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source)
            {
                foreach (var item in sequence.SelectQuery.Insert.Items)
                {
                    sequence.SelectQuery.Select.Expr(item.Expression);
                }
                break;
            }

            case 2:                      // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter)
            {
                UpdateBuilder.BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[1].Unwrap(),
                    sequence,
                    sequence.SelectQuery.Insert.Items,
                    sequence);

                sequence.SelectQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable;
                sequence.SelectQuery.From.Tables.Clear();

                break;
            }

            case 3:                      // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter)
            {
                var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

                UpdateBuilder.BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[2].Unwrap(),
                    into,
                    sequence.SelectQuery.Insert.Items,
                    sequence);

                sequence.SelectQuery.Select.Columns.Clear();

                foreach (var item in sequence.SelectQuery.Insert.Items)
                {
                    sequence.SelectQuery.Select.Columns.Add(new SelectQuery.Column(sequence.SelectQuery, item.Expression));
                }

                sequence.SelectQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable;

                break;
            }
            }

            var insert = sequence.SelectQuery.Insert;

            var q = insert.Into.Fields.Values
#if SL4
                    .Cast <ISqlExpression>()
#endif
                    .Except(insert.Items.Select(e => e.Column))
                    .OfType <SqlField>()
                    .Where(f => f.IsIdentity);

            foreach (var field in q)
            {
                var expr = builder.DataContextInfo.CreateSqlBuilder().GetIdentityExpression(insert.Into);

                if (expr != null)
                {
                    insert.Items.Insert(0, new SelectQuery.SetExpression(field, expr));

                    if (methodCall.Arguments.Count == 3)
                    {
                        sequence.SelectQuery.Select.Columns.Insert(0, new SelectQuery.Column(sequence.SelectQuery, insert.Items[0].Expression));
                    }
                }
            }

            sequence.SelectQuery.QueryType           = QueryType.Insert;
            sequence.SelectQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity";

            return(new InsertContext(buildInfo.Parent, sequence, sequence.SelectQuery.Insert.WithIdentity));
        }
예제 #5
0
 ISequenceBuilder GetBuilder(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(_builder ?? (_builder = builder.GetBuilder(buildInfo)));
 }
예제 #6
0
 public SequenceConvertInfo Convert(ExpressionBuilder builder, BuildInfo buildInfo, ParameterExpression param)
 {
     return(null);
 }
예제 #7
0
 public bool CanBuild(ExpressionBuilder builder, BuildInfo buildInfo)
 {
     return(buildInfo.Expression is ChangeTypeExpression);
 }
예제 #8
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

            return(new CastContext(sequence, methodCall));
        }
예제 #9
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var isGroup      = methodCall.Method.Name == "GroupJoin";
            var outerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0], buildInfo.SelectQuery));
            var innerContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            var context = new SubQueryContext(outerContext);

            innerContext = isGroup ? new GroupJoinSubQueryContext(innerContext) : new SubQueryContext(innerContext);

            var join = isGroup ? innerContext.SelectQuery.WeakLeftJoin() : innerContext.SelectQuery.InnerJoin();
            var sql  = context.SelectQuery;

            sql.From.Tables[0].Joins.Add(join.JoinedTable);

            var selector = (LambdaExpression)methodCall.Arguments[4].Unwrap();

            context.SetAlias(selector.Parameters[0].Name);
            innerContext.SetAlias(selector.Parameters[1].Name);

            var outerKeyLambda = ((LambdaExpression)methodCall.Arguments[2].Unwrap());
            var innerKeyLambda = ((LambdaExpression)methodCall.Arguments[3].Unwrap());

            var outerKeySelector = outerKeyLambda.Body.Unwrap();
            var innerKeySelector = innerKeyLambda.Body.Unwrap();

            var outerParent = context.Parent;
            var innerParent = innerContext.Parent;

            var outerKeyContext = new ExpressionContext(buildInfo.Parent, context, outerKeyLambda);
            var innerKeyContext = new InnerKeyContext(buildInfo.Parent, innerContext, innerKeyLambda);

            // Make join and where for the counter.
            //
            if (outerKeySelector.NodeType == ExpressionType.New)
            {
                var new1 = (NewExpression)outerKeySelector;
                var new2 = (NewExpression)innerKeySelector;

                for (var i = 0; i < new1.Arguments.Count; i++)
                {
                    var arg1 = new1.Arguments[i];
                    var arg2 = new2.Arguments[i];

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2);
                }
            }
            else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
            {
                var mi1 = (MemberInitExpression)outerKeySelector;
                var mi2 = (MemberInitExpression)innerKeySelector;

                for (var i = 0; i < mi1.Bindings.Count; i++)
                {
                    if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
                    {
                        throw new LinqException("List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type));
                    }

                    var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                    var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

                    BuildJoin(builder, join, outerKeyContext, arg1, innerKeyContext, arg2);
                }
            }
            else
            {
                BuildJoin(builder, join, outerKeyContext, outerKeySelector, innerKeyContext, innerKeySelector);
            }

            builder.ReplaceParent(outerKeyContext, outerParent);
            builder.ReplaceParent(innerKeyContext, innerParent);

            if (isGroup)
            {
                var inner = (GroupJoinSubQueryContext)innerContext;

                inner.Join = join.JoinedTable;
                inner.GetSubQueryContext = () =>
                                           GetSubQueryContext(builder, methodCall, buildInfo, sql,
                                                              innerKeyLambda, outerKeySelector, innerKeySelector, outerKeyContext);

                return(new GroupJoinContext(
                           buildInfo.Parent, selector, context, inner, methodCall.Arguments[1], outerKeyLambda, innerKeyLambda));
            }

            return(new JoinContext(buildInfo.Parent, selector, context, innerContext)
#if DEBUG
            {
                MethodCall = methodCall
            }
#endif
                   );
        }
예제 #10
0
        IBuildContext GetSubQueryContext(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo,
                                         SelectQuery sql,
                                         LambdaExpression innerKeyLambda,
                                         Expression outerKeySelector,
                                         Expression innerKeySelector,
                                         IBuildContext outerKeyContext)
        {
            var subQueryContext = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SelectQuery()));

            subQueryContext = new SubQueryContext(subQueryContext);

            var subQueryParent     = subQueryContext.Parent;
            var subQueryKeyContext = new ExpressionContext(buildInfo.Parent, subQueryContext, innerKeyLambda);

            // Process SubQuery.
            //
            var subQuerySql = ((SubQueryContext)subQueryContext).SelectQuery;

            // Make join and where for the counter.
            //
            if (outerKeySelector.NodeType == ExpressionType.New)
            {
                var new1 = (NewExpression)outerKeySelector;
                var new2 = (NewExpression)innerKeySelector;

                for (var i = 0; i < new1.Arguments.Count; i++)
                {
                    var arg1 = new1.Arguments[i];
                    var arg2 = new2.Arguments[i];

                    BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql);
                }
            }
            else if (outerKeySelector.NodeType == ExpressionType.MemberInit)
            {
                var mi1 = (MemberInitExpression)outerKeySelector;
                var mi2 = (MemberInitExpression)innerKeySelector;

                for (var i = 0; i < mi1.Bindings.Count; i++)
                {
                    if (mi1.Bindings[i].Member != mi2.Bindings[i].Member)
                    {
                        throw new LinqException("List of member inits does not match for entity type '{0}'.".Args(outerKeySelector.Type));
                    }

                    var arg1 = ((MemberAssignment)mi1.Bindings[i]).Expression;
                    var arg2 = ((MemberAssignment)mi2.Bindings[i]).Expression;

                    BuildSubQueryJoin(builder, outerKeyContext, arg1, arg2, subQueryKeyContext, subQuerySql);
                }
            }
            else
            {
                BuildSubQueryJoin(builder, outerKeyContext, outerKeySelector, innerKeySelector, subQueryKeyContext, subQuerySql);
            }

            builder.ReplaceParent(subQueryKeyContext, subQueryParent);

            subQuerySql.ParentSelect = sql;
            subQuerySql.Select.Columns.Clear();

            return(subQueryContext);
        }
예제 #11
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence           = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));
            var collectionSelector = (LambdaExpression)methodCall.Arguments[1].Unwrap();
            var resultSelector     = (LambdaExpression)methodCall.Arguments[2].Unwrap();

            if (!sequence.SelectQuery.GroupBy.IsEmpty)
            {
                sequence = new SubQueryContext(sequence);
            }

            var context = new SelectManyContext(buildInfo.Parent, collectionSelector, sequence);
            var expr    = collectionSelector.Body.Unwrap();

            var collectionInfo = new BuildInfo(context, expr, new SelectQuery());
            var collection     = builder.BuildSequence(collectionInfo);
            var leftJoin       = collection is DefaultIfEmptyBuilder.DefaultIfEmptyContext;
            var sql            = collection.SelectQuery;

            var sequenceTables = new HashSet <ISqlTableSource>(sequence.SelectQuery.From.Tables[0].GetTables());
            var newQuery       = null != new QueryVisitor().Find(sql, e => e == collectionInfo.SelectQuery);
            var crossApply     = null != new QueryVisitor().Find(sql, e =>
                                                                 e.ElementType == QueryElementType.TableSource && sequenceTables.Contains((ISqlTableSource)e) ||
                                                                 e.ElementType == QueryElementType.SqlField && sequenceTables.Contains(((SqlField)e).Table) ||
                                                                 e.ElementType == QueryElementType.Column && sequenceTables.Contains(((SelectQuery.Column)e).Parent));

            if (collection is JoinBuilder.GroupJoinSubQueryContext)
            {
                var groupJoin = ((JoinBuilder.GroupJoinSubQueryContext)collection).GroupJoin;

                groupJoin.SelectQuery.From.Tables[0].Joins[0].JoinType = SelectQuery.JoinType.Inner;
                groupJoin.SelectQuery.From.Tables[0].Joins[0].IsWeak   = false;
            }

            if (!newQuery)
            {
                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }

            if (!crossApply)
            {
                if (!leftJoin)
                {
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, true);
                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
                else
                {
                    var join = SelectQuery.OuterApply(sql);
                    sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                    context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);

                    return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
                }
            }

            if (collection is TableBuilder.TableContext)
            {
                var table = (TableBuilder.TableContext)collection;

                var join = table.SqlTable.TableArguments != null && table.SqlTable.TableArguments.Length > 0 ?
                           (leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql)) :
                           (leftJoin ? SelectQuery.LeftJoin(sql) : SelectQuery.InnerJoin(sql));

                join.JoinedTable.Condition.Conditions.AddRange(sql.Where.SearchCondition.Conditions);
                join.JoinedTable.CanConvertApply = false;

                sql.Where.SearchCondition.Conditions.Clear();

                var collectionParent = collection.Parent as TableBuilder.TableContext;

                // Association.
                //
                if (collectionParent != null && collectionInfo.IsAssociationBuilt)
                {
                    var ts = (SelectQuery.TableSource) new QueryVisitor().Find(sequence.SelectQuery.From, e =>
                    {
                        if (e.ElementType == QueryElementType.TableSource)
                        {
                            var t = (SelectQuery.TableSource)e;
                            return(t.Source == collectionParent.SqlTable);
                        }

                        return(false);
                    });

                    ts.Joins.Add(join.JoinedTable);
                }
                else
                {
                    sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);
                }

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
            else
            {
                var join = leftJoin ? SelectQuery.OuterApply(sql) : SelectQuery.CrossApply(sql);
                sequence.SelectQuery.From.Tables[0].Joins.Add(join.JoinedTable);

                context.Collection = new SubQueryContext(collection, sequence.SelectQuery, false);
                return(new SelectContext(buildInfo.Parent, resultSelector, sequence, context));
            }
        }