Example #1
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));
        }
Example #2
0
        protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo)
        {
            var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0]));

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

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

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

            if (methodCall.Arguments.Count == 3)
            {
                var table = sequence.SelectQuery.Insert.Into;
                var keys  = table.GetKeys(false);

                if (keys.Count == 0)
                {
                    throw new LinqException("InsertOrUpdate method requires the '{0}' table to have a primary key.", table.Name);
                }

                var q =
                    (
                        from k in keys
                        join i in sequence.SelectQuery.Insert.Items on k equals i.Column
                        select new { k, i }
                    ).ToList();

                var missedKey = keys.Except(q.Select(i => i.k)).FirstOrDefault();

                if (missedKey != null)
                {
                    throw new LinqException("InsertOrUpdate method requires the '{0}.{1}' field to be included in the insert setter.",
                                            table.Name,
                                            ((SqlField)missedKey).Name);
                }

                sequence.SelectQuery.Update.Keys.AddRange(q.Select(i => i.i));
            }
            else
            {
                UpdateBuilder.BuildSetter(
                    builder,
                    buildInfo,
                    (LambdaExpression)methodCall.Arguments[3].Unwrap(),
                    sequence,
                    sequence.SelectQuery.Update.Keys,
                    sequence);
            }

            sequence.SelectQuery.QueryType = QueryType.InsertOrUpdate;

            return(new InsertOrUpdateContext(buildInfo.Parent, sequence));
        }