protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SqlQuery.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.SqlQuery.Set.Items) { sequence.SqlQuery.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); sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.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 SqlQuery())); UpdateBuilder.BuildSetter(builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence); sequence.SqlQuery.Select.Columns.Clear(); foreach (var item in sequence.SqlQuery.Set.Items) { sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); } sequence.SqlQuery.Set.Into = ((TableBuilder.TableContext)into).SqlTable; break; } } sequence.SqlQuery.QueryType = QueryType.Insert; sequence.SqlQuery.Set.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Set.WithIdentity)); }
protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) { var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); var isSubQuery = sequence.SqlQuery.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.SqlQuery.Insert.Items) { sequence.SqlQuery.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.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.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 SqlQuery())); UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), into, sequence.SqlQuery.Insert.Items, sequence); sequence.SqlQuery.Select.Columns.Clear(); foreach (var item in sequence.SqlQuery.Insert.Items) { sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); } sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable; break; } } var insert = sequence.SqlQuery.Insert; var q = insert.Into.Fields.Values.Cast <ISqlExpression>().Except(insert.Items.Select(e => e.Column)) .OfType <SqlField>() .Where(f => f.IsIdentity); foreach (var field in q) { var expr = builder.SqlProvider.GetIdentityExpression(insert.Into, field, false); if (expr != null) { insert.Items.Insert(0, new SqlQuery.SetExpression(field, expr)); if (methodCall.Arguments.Count == 3) { sequence.SqlQuery.Select.Columns.Insert(0, new SqlQuery.Column(sequence.SqlQuery, insert.Items[0].Expression)); } } } sequence.SqlQuery.QueryType = QueryType.Insert; sequence.SqlQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; sequence.SqlQuery.Insert.WithOutput = methodCall.Method.Name == "InsertWithOutput"; return(new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity || sequence.SqlQuery.Insert.WithOutput)); }
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.SqlQuery.Insert.Items, sequence); UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[2].Unwrap(), sequence, sequence.SqlQuery.Update.Items, sequence); sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.Update.Table = ((TableBuilder.TableContext)sequence).SqlTable; sequence.SqlQuery.From.Tables.Clear(); sequence.SqlQuery.From.Table(sequence.SqlQuery.Update.Table); if (methodCall.Arguments.Count == 3) { var table = sequence.SqlQuery.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.SqlQuery.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.SqlQuery.Update.Keys.AddRange(q.Select(i => i.i)); } else { UpdateBuilder.BuildSetter( builder, buildInfo, (LambdaExpression)methodCall.Arguments[3].Unwrap(), sequence, sequence.SqlQuery.Update.Keys, sequence); } sequence.SqlQuery.QueryType = QueryType.InsertOrUpdate; return(new InsertOrUpdateContext(buildInfo.Parent, sequence)); }