Mercurial > pub > bltoolkit
comparison Source/Data/Linq/Builder/InsertBuilder.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:f990fcb411a9 |
---|---|
1 using System; | |
2 using System.Linq; | |
3 using System.Linq.Expressions; | |
4 | |
5 namespace BLToolkit.Data.Linq.Builder | |
6 { | |
7 using BLToolkit.Linq; | |
8 using Data.Sql; | |
9 | |
10 class InsertBuilder : MethodCallBuilder | |
11 { | |
12 #region InsertBuilder | |
13 | |
14 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
15 { | |
16 return methodCall.IsQueryable("Insert", "InsertWithIdentity"); | |
17 } | |
18 | |
19 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
20 { | |
21 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
22 | |
23 var isSubQuery = sequence.SqlQuery.Select.IsDistinct; | |
24 | |
25 if (isSubQuery) | |
26 sequence = new SubQueryContext(sequence); | |
27 | |
28 switch (methodCall.Arguments.Count) | |
29 { | |
30 case 1 : | |
31 // static int Insert<T> (this IValueInsertable<T> source) | |
32 // static int Insert<TSource,TTarget>(this ISelectInsertable<TSource,TTarget> source) | |
33 { | |
34 foreach (var item in sequence.SqlQuery.Insert.Items) | |
35 sequence.SqlQuery.Select.Expr(item.Expression); | |
36 break; | |
37 } | |
38 | |
39 case 2 : // static int Insert<T>(this Table<T> target, Expression<Func<T>> setter) | |
40 { | |
41 UpdateBuilder.BuildSetter( | |
42 builder, | |
43 buildInfo, | |
44 (LambdaExpression)methodCall.Arguments[1].Unwrap(), | |
45 sequence, | |
46 sequence.SqlQuery.Insert.Items, | |
47 sequence); | |
48 | |
49 sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; | |
50 sequence.SqlQuery.From.Tables.Clear(); | |
51 | |
52 break; | |
53 } | |
54 | |
55 case 3 : // static int Insert<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target, Expression<Func<TSource,TTarget>> setter) | |
56 { | |
57 var into = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[1], new SqlQuery())); | |
58 | |
59 UpdateBuilder.BuildSetter( | |
60 builder, | |
61 buildInfo, | |
62 (LambdaExpression)methodCall.Arguments[2].Unwrap(), | |
63 into, | |
64 sequence.SqlQuery.Insert.Items, | |
65 sequence); | |
66 | |
67 sequence.SqlQuery.Select.Columns.Clear(); | |
68 | |
69 foreach (var item in sequence.SqlQuery.Insert.Items) | |
70 sequence.SqlQuery.Select.Columns.Add(new SqlQuery.Column(sequence.SqlQuery, item.Expression)); | |
71 | |
72 sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)into).SqlTable; | |
73 | |
74 break; | |
75 } | |
76 } | |
77 | |
78 var insert = sequence.SqlQuery.Insert; | |
79 | |
80 var q = insert.Into.Fields.Values.Cast<ISqlExpression>().Except(insert.Items.Select(e => e.Column)) | |
81 .OfType<SqlField>() | |
82 .Where(f => f.IsIdentity); | |
83 | |
84 foreach (var field in q) | |
85 { | |
86 var expr = builder.SqlProvider.GetIdentityExpression(insert.Into, field, false); | |
87 | |
88 if (expr != null) | |
89 { | |
90 insert.Items.Insert(0, new SqlQuery.SetExpression(field, expr)); | |
91 | |
92 if (methodCall.Arguments.Count == 3) | |
93 { | |
94 sequence.SqlQuery.Select.Columns.Insert(0, new SqlQuery.Column(sequence.SqlQuery, insert.Items[0].Expression)); | |
95 } | |
96 } | |
97 } | |
98 | |
99 sequence.SqlQuery.QueryType = QueryType.Insert; | |
100 sequence.SqlQuery.Insert.WithIdentity = methodCall.Method.Name == "InsertWithIdentity"; | |
101 | |
102 return new InsertContext(buildInfo.Parent, sequence, sequence.SqlQuery.Insert.WithIdentity); | |
103 } | |
104 | |
105 protected override SequenceConvertInfo Convert( | |
106 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
107 { | |
108 return null; | |
109 } | |
110 | |
111 #endregion | |
112 | |
113 #region InsertContext | |
114 | |
115 class InsertContext : SequenceContextBase | |
116 { | |
117 public InsertContext(IBuildContext parent, IBuildContext sequence, bool insertWithIdentity) | |
118 : base(parent, sequence, null) | |
119 { | |
120 _insertWithIdentity = insertWithIdentity; | |
121 } | |
122 | |
123 readonly bool _insertWithIdentity; | |
124 | |
125 public override void BuildQuery<T>(Query<T> query, ParameterExpression queryParameter) | |
126 { | |
127 if (_insertWithIdentity) query.SetScalarQuery<object>(); | |
128 else query.SetNonQueryQuery(); | |
129 } | |
130 | |
131 public override Expression BuildExpression(Expression expression, int level) | |
132 { | |
133 throw new InvalidOperationException(); | |
134 } | |
135 | |
136 public override SqlInfo[] ConvertToSql(Expression expression, int level, ConvertFlags flags) | |
137 { | |
138 throw new InvalidOperationException(); | |
139 } | |
140 | |
141 public override SqlInfo[] ConvertToIndex(Expression expression, int level, ConvertFlags flags) | |
142 { | |
143 throw new InvalidOperationException(); | |
144 } | |
145 | |
146 public override IsExpressionResult IsExpression(Expression expression, int level, RequestFor requestFlag) | |
147 { | |
148 throw new InvalidOperationException(); | |
149 } | |
150 | |
151 public override IBuildContext GetContext(Expression expression, int level, BuildInfo buildInfo) | |
152 { | |
153 throw new InvalidOperationException(); | |
154 } | |
155 } | |
156 | |
157 #endregion | |
158 | |
159 #region Into | |
160 | |
161 internal class Into : MethodCallBuilder | |
162 { | |
163 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
164 { | |
165 return methodCall.IsQueryable("Into"); | |
166 } | |
167 | |
168 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
169 { | |
170 var source = methodCall.Arguments[0].Unwrap(); | |
171 var into = methodCall.Arguments[1].Unwrap(); | |
172 | |
173 IBuildContext sequence; | |
174 | |
175 // static IValueInsertable<T> Into<T>(this IDataContext dataContext, Table<T> target) | |
176 // | |
177 if (source.NodeType == ExpressionType.Constant && ((ConstantExpression)source).Value == null) | |
178 { | |
179 sequence = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery())); | |
180 | |
181 if (sequence.SqlQuery.Select.IsDistinct) | |
182 sequence = new SubQueryContext(sequence); | |
183 | |
184 sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)sequence).SqlTable; | |
185 sequence.SqlQuery.From.Tables.Clear(); | |
186 } | |
187 // static ISelectInsertable<TSource,TTarget> Into<TSource,TTarget>(this IQueryable<TSource> source, Table<TTarget> target) | |
188 // | |
189 else | |
190 { | |
191 sequence = builder.BuildSequence(new BuildInfo(buildInfo, source)); | |
192 | |
193 if (sequence.SqlQuery.Select.IsDistinct) | |
194 sequence = new SubQueryContext(sequence); | |
195 | |
196 var tbl = builder.BuildSequence(new BuildInfo((IBuildContext)null, into, new SqlQuery())); | |
197 sequence.SqlQuery.Insert.Into = ((TableBuilder.TableContext)tbl).SqlTable; | |
198 } | |
199 | |
200 sequence.SqlQuery.Select.Columns.Clear(); | |
201 | |
202 return sequence; | |
203 } | |
204 | |
205 protected override SequenceConvertInfo Convert( | |
206 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
207 { | |
208 return null; | |
209 } | |
210 } | |
211 | |
212 #endregion | |
213 | |
214 #region Value | |
215 | |
216 internal class Value : MethodCallBuilder | |
217 { | |
218 protected override bool CanBuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
219 { | |
220 return methodCall.IsQueryable("Value"); | |
221 } | |
222 | |
223 protected override IBuildContext BuildMethodCall(ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo) | |
224 { | |
225 var sequence = builder.BuildSequence(new BuildInfo(buildInfo, methodCall.Arguments[0])); | |
226 var extract = (LambdaExpression)methodCall.Arguments[1].Unwrap(); | |
227 var update = methodCall.Arguments[2].Unwrap(); | |
228 | |
229 if (sequence.SqlQuery.Insert.Into == null) | |
230 { | |
231 sequence.SqlQuery.Insert.Into = (SqlTable)sequence.SqlQuery.From.Tables[0].Source; | |
232 sequence.SqlQuery.From.Tables.Clear(); | |
233 } | |
234 | |
235 if (update.NodeType == ExpressionType.Lambda) | |
236 UpdateBuilder.ParseSet( | |
237 builder, | |
238 buildInfo, | |
239 extract, | |
240 (LambdaExpression)update, | |
241 sequence, | |
242 sequence.SqlQuery.Insert.Into, | |
243 sequence.SqlQuery.Insert.Items); | |
244 else | |
245 UpdateBuilder.ParseSet( | |
246 builder, | |
247 buildInfo, | |
248 extract, | |
249 update, | |
250 sequence, | |
251 sequence.SqlQuery.Insert.Items); | |
252 | |
253 return sequence; | |
254 } | |
255 | |
256 protected override SequenceConvertInfo Convert( | |
257 ExpressionBuilder builder, MethodCallExpression methodCall, BuildInfo buildInfo, ParameterExpression param) | |
258 { | |
259 return null; | |
260 } | |
261 } | |
262 | |
263 #endregion | |
264 } | |
265 } |