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 }