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