Mercurial > pub > bltoolkit
comparison Source/DataAccess/SqlQueryBase.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.Collections; | |
3 using System.Collections.Generic; | |
4 using System.Text; | |
5 | |
6 using BLToolkit.Aspects; | |
7 using BLToolkit.Data; | |
8 using BLToolkit.Data.DataProvider; | |
9 using BLToolkit.Mapping; | |
10 using BLToolkit.Reflection; | |
11 using BLToolkit.Reflection.Extension; | |
12 | |
13 namespace BLToolkit.DataAccess | |
14 { | |
15 public abstract class SqlQueryBase : DataAccessorBase | |
16 { | |
17 #region Constructors | |
18 | |
19 protected SqlQueryBase() | |
20 { | |
21 } | |
22 | |
23 protected SqlQueryBase(DbManager dbManager) | |
24 : base(dbManager) | |
25 { | |
26 } | |
27 | |
28 protected SqlQueryBase(DbManager dbManager, bool dispose) | |
29 : base(dbManager, dispose) | |
30 { | |
31 } | |
32 | |
33 #endregion | |
34 | |
35 #region Protected Members | |
36 | |
37 [NoInterception] | |
38 protected virtual MemberMapper[] GetFieldList(ObjectMapper om) | |
39 { | |
40 var list = new List<MemberMapper>(om.Count); | |
41 | |
42 foreach (MemberMapper mm in om) | |
43 if (mm.MapMemberInfo.SqlIgnore == false) | |
44 list.Add(mm); | |
45 | |
46 return list.ToArray(); | |
47 } | |
48 | |
49 [NoInterception] | |
50 protected virtual MemberMapper[] GetNonKeyFieldList(ObjectMapper om) | |
51 { | |
52 var typeExt = TypeExtension.GetTypeExtension(om.TypeAccessor.OriginalType, Extensions); | |
53 var list = new List<MemberMapper>(); | |
54 | |
55 foreach (MemberMapper mm in om) | |
56 { | |
57 if (mm.MapMemberInfo.SqlIgnore) | |
58 continue; | |
59 | |
60 var ma = mm.MapMemberInfo.MemberAccessor; | |
61 | |
62 bool isSet; | |
63 MappingSchema.MetadataProvider.GetPrimaryKeyOrder(om.TypeAccessor.OriginalType, typeExt, ma, out isSet); | |
64 | |
65 if (!isSet) | |
66 list.Add(mm); | |
67 } | |
68 | |
69 return list.ToArray(); | |
70 } | |
71 | |
72 struct MemberOrder | |
73 { | |
74 public MemberOrder(MemberMapper memberMapper, int order) | |
75 { | |
76 MemberMapper = memberMapper; | |
77 Order = order; | |
78 } | |
79 | |
80 public readonly MemberMapper MemberMapper; | |
81 public readonly int Order; | |
82 } | |
83 | |
84 private static readonly Hashtable _keyList = new Hashtable(); | |
85 | |
86 [NoInterception] | |
87 protected internal virtual MemberMapper[] GetKeyFieldList(DbManager db, Type type) | |
88 { | |
89 var key = type.FullName + "$" + db.DataProvider.UniqueName; | |
90 var mmList = (MemberMapper[])_keyList[key]; | |
91 | |
92 if (mmList == null) | |
93 { | |
94 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
95 var list = new List<MemberOrder>(); | |
96 | |
97 foreach (MemberMapper mm in db.MappingSchema.GetObjectMapper(type)) | |
98 { | |
99 if (mm.MapMemberInfo.SqlIgnore) | |
100 continue; | |
101 | |
102 var ma = mm.MapMemberInfo.MemberAccessor; | |
103 | |
104 if (TypeHelper.IsScalar(ma.Type)) | |
105 { | |
106 bool isSet; | |
107 var order = MappingSchema.MetadataProvider.GetPrimaryKeyOrder(type, typeExt, ma, out isSet); | |
108 | |
109 if (isSet) | |
110 list.Add(new MemberOrder(mm, order)); | |
111 } | |
112 } | |
113 | |
114 list.Sort((x, y) => x.Order - y.Order); | |
115 | |
116 _keyList[key] = mmList = new MemberMapper[list.Count]; | |
117 | |
118 for (var i = 0; i < list.Count; i++) | |
119 mmList[i] = list[i].MemberMapper; | |
120 } | |
121 | |
122 return mmList; | |
123 } | |
124 | |
125 [NoInterception] | |
126 protected virtual void AddWherePK(DbManager db, SqlQueryInfo query, StringBuilder sb, int nParameter) | |
127 { | |
128 sb.Append("WHERE\n"); | |
129 | |
130 var memberMappers = GetKeyFieldList(db, query.ObjectType); | |
131 | |
132 if (memberMappers.Length == 0) | |
133 throw new DataAccessException( | |
134 string.Format("No primary key field(s) in the type '{0}'.", query.ObjectType.FullName)); | |
135 | |
136 foreach (var mm in memberMappers) | |
137 { | |
138 var p = query.AddParameter( | |
139 db.DataProvider.Convert(mm.Name + "_W", ConvertType.NameToQueryParameter).ToString(), | |
140 mm.Name); | |
141 | |
142 sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField)); | |
143 | |
144 if (nParameter < 0) | |
145 sb.AppendFormat("{0} AND\n", p.ParameterName); | |
146 else | |
147 sb.AppendFormat("{{{0}}} AND\n", nParameter++); | |
148 } | |
149 | |
150 sb.Remove(sb.Length - 5, 5); | |
151 } | |
152 | |
153 protected SqlQueryInfo CreateSelectByKeySqlText(DbManager db, Type type) | |
154 { | |
155 var om = db.MappingSchema.GetObjectMapper(type); | |
156 var sb = new StringBuilder(); | |
157 var query = new SqlQueryInfo(om); | |
158 | |
159 sb.Append("SELECT\n"); | |
160 | |
161 foreach (var mm in GetFieldList(om)) | |
162 sb.AppendFormat("\t{0},\n", | |
163 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
164 | |
165 sb.Remove(sb.Length - 2, 1); | |
166 | |
167 sb.Append("FROM\n\t"); | |
168 | |
169 AppendTableName(sb, db, type); | |
170 | |
171 AddWherePK(db, query, sb, -1); | |
172 | |
173 query.QueryText = sb.ToString(); | |
174 | |
175 return query; | |
176 } | |
177 | |
178 // NOTE changed to virtual | |
179 protected virtual void AppendTableName(StringBuilder sb, DbManager db, Type type) | |
180 { | |
181 var database = GetDatabaseName(type); | |
182 var owner = GetOwnerName (type); | |
183 var name = GetTableName (type); | |
184 | |
185 db.DataProvider.CreateSqlProvider().BuildTableName(sb, | |
186 database == null ? null : db.DataProvider.Convert(database, ConvertType.NameToDatabase). ToString(), | |
187 owner == null ? null : db.DataProvider.Convert(owner, ConvertType.NameToOwner). ToString(), | |
188 name == null ? null : db.DataProvider.Convert(name, ConvertType.NameToQueryTable).ToString()); | |
189 | |
190 sb.AppendLine(); | |
191 } | |
192 | |
193 protected SqlQueryInfo CreateSelectAllSqlText(DbManager db, Type type) | |
194 { | |
195 var om = db.MappingSchema.GetObjectMapper(type); | |
196 var sb = new StringBuilder(); | |
197 var query = new SqlQueryInfo(om); | |
198 | |
199 sb.Append("SELECT\n"); | |
200 | |
201 foreach (var mm in GetFieldList(om)) | |
202 sb.AppendFormat("\t{0},\n", | |
203 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
204 | |
205 sb.Remove(sb.Length - 2, 1); | |
206 | |
207 sb.Append("FROM\n\t"); | |
208 AppendTableName(sb, db, type); | |
209 | |
210 query.QueryText = sb.ToString(); | |
211 | |
212 return query; | |
213 } | |
214 | |
215 protected SqlQueryInfo CreateInsertSqlText(DbManager db, Type type, int nParameter) | |
216 { | |
217 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
218 var om = db.MappingSchema.GetObjectMapper(type); | |
219 var list = new List<MemberMapper>(); | |
220 var sb = new StringBuilder(); | |
221 var query = new SqlQueryInfo(om); | |
222 var mp = MappingSchema.MetadataProvider; | |
223 | |
224 sb.Append("INSERT INTO "); | |
225 AppendTableName(sb, db, type); | |
226 sb.Append(" (\n"); | |
227 | |
228 foreach (var mm in GetFieldList(om)) | |
229 { | |
230 // IT: This works incorrectly for complex mappers. | |
231 // | |
232 // [2009-03-24] ili: use mm.MemberAccessor instead of mm.ComplexMemberAccessor | |
233 // as in CreateUpdateSqlText | |
234 // | |
235 | |
236 bool isSet; | |
237 var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
238 | |
239 if (nonUpdatableAttribute == null || !isSet || nonUpdatableAttribute.OnInsert == false) | |
240 { | |
241 sb.AppendFormat("\t{0},\n", | |
242 db.DataProvider.Convert(mm.Name, ConvertType.NameToQueryField)); | |
243 list.Add(mm); | |
244 } | |
245 } | |
246 | |
247 sb.Remove(sb.Length - 2, 1); | |
248 | |
249 sb.Append(") VALUES (\n"); | |
250 | |
251 foreach (var mm in list) | |
252 { | |
253 var p = query.AddParameter( | |
254 db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(), | |
255 mm.Name); | |
256 | |
257 if (nParameter < 0) | |
258 sb.AppendFormat("\t{0},\n", p.ParameterName); | |
259 //sb.AppendFormat("\t{0},\n", db.DataProvider.Convert(p.ParameterName, ConvertType.NameToQueryParameter)); | |
260 else | |
261 sb.AppendFormat("\t{{{0}}},\n", nParameter++); | |
262 } | |
263 | |
264 sb.Remove(sb.Length - 2, 1); | |
265 | |
266 sb.Append(")"); | |
267 | |
268 query.QueryText = sb.ToString(); | |
269 | |
270 return query; | |
271 } | |
272 | |
273 protected SqlQueryInfo CreateUpdateSqlText(DbManager db, Type type, int nParameter) | |
274 { | |
275 var typeExt = TypeExtension.GetTypeExtension(type, Extensions); | |
276 var om = db.MappingSchema.GetObjectMapper(type); | |
277 var sb = new StringBuilder(); | |
278 var query = new SqlQueryInfo(om); | |
279 var mp = MappingSchema.MetadataProvider; | |
280 | |
281 sb.Append("UPDATE\n\t"); | |
282 AppendTableName(sb, db, type); | |
283 sb.Append("\nSET\n"); | |
284 | |
285 var fields = GetFieldList(om); | |
286 var hasFields = false; | |
287 | |
288 foreach (var mm in fields) | |
289 { | |
290 bool isSet; | |
291 | |
292 var nonUpdatableAttribute = mp.GetNonUpdatableAttribute(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
293 | |
294 if (nonUpdatableAttribute != null && isSet && nonUpdatableAttribute.OnUpdate == true) | |
295 continue; | |
296 | |
297 mp.GetPrimaryKeyOrder(type, typeExt, mm.MapMemberInfo.MemberAccessor, out isSet); | |
298 | |
299 if (isSet) | |
300 continue; | |
301 | |
302 hasFields = true; | |
303 | |
304 var p = query.AddParameter( | |
305 db.DataProvider.Convert(mm.Name + "_P", ConvertType.NameToQueryParameter).ToString(), | |
306 mm.Name); | |
307 | |
308 sb.AppendFormat("\t{0} = ", db.DataProvider.Convert(p.FieldName, ConvertType.NameToQueryField)); | |
309 | |
310 if (nParameter < 0) | |
311 sb.AppendFormat("{0},\n", p.ParameterName); | |
312 else | |
313 sb.AppendFormat("\t{{{0}}},\n", nParameter++); | |
314 } | |
315 | |
316 if (!hasFields) | |
317 throw new DataAccessException( | |
318 string.Format("There are no fields to update in the type '{0}'.", query.ObjectType.FullName)); | |
319 | |
320 sb.Remove(sb.Length - 2, 1); | |
321 | |
322 AddWherePK(db, query, sb, nParameter); | |
323 | |
324 query.QueryText = sb.ToString(); | |
325 | |
326 return query; | |
327 } | |
328 | |
329 protected SqlQueryInfo CreateDeleteSqlText(DbManager db, Type type, int nParameter) | |
330 { | |
331 var om = db.MappingSchema.GetObjectMapper(type); | |
332 var sb = new StringBuilder(); | |
333 var query = new SqlQueryInfo(om); | |
334 | |
335 sb.Append("DELETE FROM\n\t"); | |
336 AppendTableName(sb, db, type); | |
337 sb.AppendLine(); | |
338 | |
339 AddWherePK(db, query, sb, nParameter); | |
340 | |
341 query.QueryText = sb.ToString(); | |
342 | |
343 return query; | |
344 } | |
345 | |
346 [NoInterception] | |
347 protected virtual SqlQueryInfo CreateSqlText(DbManager db, Type type, string actionName) | |
348 { | |
349 switch (actionName) | |
350 { | |
351 case "SelectByKey": return CreateSelectByKeySqlText(db, type); | |
352 case "SelectAll": return CreateSelectAllSqlText (db, type); | |
353 case "Insert": return CreateInsertSqlText (db, type, -1); | |
354 case "InsertBatch": return CreateInsertSqlText (db, type, 0); | |
355 case "Update": return CreateUpdateSqlText (db, type, -1); | |
356 case "UpdateBatch": return CreateUpdateSqlText (db, type, 0); | |
357 case "Delete": return CreateDeleteSqlText (db, type, -1); | |
358 case "DeleteBatch": return CreateDeleteSqlText (db, type, 0); | |
359 default: | |
360 throw new DataAccessException( | |
361 string.Format("Unknown action '{0}'.", actionName)); | |
362 } | |
363 } | |
364 | |
365 private static readonly Hashtable _actionSqlQueryInfo = new Hashtable(); | |
366 | |
367 [NoInterception] | |
368 public virtual SqlQueryInfo GetSqlQueryInfo(DbManager db, Type type, string actionName) | |
369 { | |
370 var key = type.FullName + "$" + actionName + "$" + db.DataProvider.UniqueName + "$" + GetTableName(type); | |
371 var query = (SqlQueryInfo)_actionSqlQueryInfo[key]; | |
372 | |
373 if (query == null) | |
374 { | |
375 query = CreateSqlText(db, type, actionName); | |
376 _actionSqlQueryInfo[key] = query; | |
377 } | |
378 | |
379 return query; | |
380 } | |
381 | |
382 #endregion | |
383 } | |
384 } |