comparison Source/DataAccess/DataAccessor.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.Data;
5 using System.Data.SqlTypes;
6 using System.Diagnostics;
7 using System.IO;
8 using System.Reflection;
9 using System.Xml;
10 #if !SILVERLIGHT
11 using System.Xml.Linq;
12 #endif
13
14 namespace BLToolkit.DataAccess
15 {
16 using Aspects;
17 using Common;
18 using Data;
19 using Data.DataProvider;
20 using Mapping;
21 using Patterns;
22 using Properties;
23 using Reflection;
24 using TypeBuilder;
25
26 [DataAccessor, DebuggerStepThrough]
27 public abstract class DataAccessor : DataAccessorBase
28 {
29 #region Constructors
30
31 protected DataAccessor()
32 {
33 }
34
35 protected DataAccessor(DbManager dbManager)
36 : base(dbManager)
37 {
38 }
39
40 protected DataAccessor(DbManager dbManager, bool dispose)
41 : base(dbManager, dispose)
42 {
43 }
44
45 #endregion
46
47 #region CreateInstance
48
49 public static DataAccessor CreateInstance(Type type)
50 {
51 return (DataAccessor)Activator.CreateInstance(TypeFactory.GetType(type));
52 }
53
54 public static DataAccessor CreateInstance(Type type, InitContext context)
55 {
56 return (DataAccessor)Activator.CreateInstance(TypeFactory.GetType(type), context);
57 }
58
59 public static DataAccessor CreateInstance(Type type, DbManager dbManager)
60 {
61 return CreateInstance(type, dbManager, false);
62 }
63
64 public static DataAccessor CreateInstance(
65 Type type,
66 InitContext context,
67 DbManager dbManager)
68 {
69 return CreateInstance(type, context, dbManager, false);
70 }
71
72 public static DataAccessor CreateInstance(Type type, DbManager dbManager, bool dispose)
73 {
74 var da = CreateInstance(type);
75
76 da.SetDbManager(dbManager, dispose);
77
78 return da;
79 }
80
81 public static DataAccessor CreateInstance(
82 Type type,
83 InitContext context,
84 DbManager dbManager,
85 bool dispose)
86 {
87 var da = CreateInstance(type, context);
88
89 da.SetDbManager(dbManager, dispose);
90
91 return da;
92 }
93
94 public static T CreateInstance<T>() where T : DataAccessor
95 {
96 return TypeFactory.CreateInstance<T>();
97 }
98
99 public static T CreateInstance<T>(DbManager dbManager)
100 where T : DataAccessor
101 {
102 return CreateInstance<T>(dbManager, false);
103 }
104
105 public static T CreateInstance<T>(DbManager dbManager, bool dispose)
106 where T : DataAccessor
107 {
108 var da = TypeFactory.CreateInstance<T>();
109
110 da.SetDbManager(dbManager, dispose);
111
112 return da;
113 }
114
115 #endregion
116
117 #region Protected Members
118
119 #region Parameters
120
121 [NoInterception]
122 protected virtual string GetQueryParameterName(DbManager db, string paramName)
123 {
124 return (string)db.DataProvider.Convert(paramName, ConvertType.NameToQueryParameter);
125 }
126
127 [NoInterception]
128 protected virtual string GetSpParameterName(DbManager db, string paramName)
129 {
130 return (string)db.DataProvider.Convert(paramName, db.GetConvertTypeToParameter());
131 }
132
133 [NoInterception]
134 protected virtual IDbDataParameter[] PrepareParameters(DbManager db, object[] parameters)
135 {
136 return db.PrepareParameters(parameters);
137 }
138
139 [NoInterception]
140 protected virtual IDbDataParameter GetParameter(DbManager db, string paramName)
141 {
142 var p = db.Parameter(paramName);
143
144 if (p == null)
145 {
146 // This usually means that the parameter name is incorrect.
147 //
148 throw new DataAccessException(string.Format(
149 Resources.DataAccessot_ParameterNotFound, paramName));
150 }
151
152 // Input parameter mapping make no sence.
153 //
154 Debug.WriteLineIf(p.Direction == ParameterDirection.Input,
155 string.Format("'{0}.{1}' is an input parameter.",
156 db.Command.CommandText, paramName));
157
158 return p;
159 }
160
161 [NoInterception]
162 protected virtual IDbDataParameter[] CreateParameters(
163 DbManager db,
164 object obj,
165 string[] outputParameters,
166 string[] inputOutputParameters,
167 string[] ignoreParameters,
168 params IDbDataParameter[] commandParameters)
169 {
170 return db.CreateParameters(obj, outputParameters,
171 inputOutputParameters, ignoreParameters, commandParameters);
172 }
173
174 [NoInterception]
175 protected virtual IDbDataParameter[] CreateParameters(
176 DbManager db,
177 DataRow dataRow,
178 string[] outputParameters,
179 string[] inputOutputParameters,
180 string[] ignoreParameters,
181 params IDbDataParameter[] commandParameters)
182 {
183 return db.CreateParameters(dataRow, outputParameters,
184 inputOutputParameters, ignoreParameters, commandParameters);
185 }
186
187 [NoInterception]
188 protected virtual string PrepareSqlQuery(DbManager db, int queryID, int uniqueID, string sqlQuery)
189 {
190 return sqlQuery;
191 }
192
193 #endregion
194
195 #region ExecuteDictionary
196
197 protected void ExecuteDictionary(
198 DbManager db,
199 IDictionary dictionary,
200 Type objectType,
201 Type keyType,
202 string methodName)
203 {
204 var isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType);
205 var mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
206
207 if (mms.Length == 0)
208 throw new DataAccessException(string.Format(
209 Resources.DataAccessor_UnknownIndex,
210 GetType().Name, methodName));
211
212 if (mms.Length > 1 && keyType != typeof(object) && !isIndex)
213 throw new DataAccessException(string.Format(
214 Resources.DataAccessor_InvalidKeyType,
215 GetType().Name, methodName));
216
217 if (isIndex || mms.Length > 1)
218 {
219 var fields = new string[mms.Length];
220
221 for (var i = 0; i < mms.Length; i++)
222 fields[i] = mms[i].MemberName;
223
224 db.ExecuteDictionary(dictionary, new MapIndex(fields), objectType, null);
225 }
226 else
227 {
228 db.ExecuteDictionary(dictionary, mms[0].MemberName, objectType, null);
229 }
230 }
231
232 protected void ExecuteDictionary<TValue>(
233 DbManager db,
234 IDictionary<CompoundValue, TValue> dictionary,
235 Type objectType,
236 string methodName)
237 {
238 var mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
239
240 if (mms.Length == 0)
241 throw new DataAccessException(string.Format(
242 Resources.DataAccessor_UnknownIndex,
243 GetType().Name, methodName));
244
245 var fields = new string[mms.Length];
246
247 for (var i = 0; i < mms.Length; i++)
248 fields[i] = mms[i].MemberName;
249
250 db.ExecuteDictionary(dictionary, new MapIndex(fields), objectType, null);
251 }
252
253 protected void ExecuteDictionary<TKey, TValue>(
254 DbManager db,
255 IDictionary<TKey, TValue> dictionary,
256 Type objectType,
257 string methodName)
258 {
259 var mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
260
261 if (mms.Length == 0)
262 throw new DataAccessException(string.Format(
263 Resources.DataAccessor_UnknownIndex,
264 GetType().Name, methodName));
265
266 if (mms.Length != 1)
267 throw new DataAccessException(string.Format(
268 Resources.DataAccessor_IndexIsComplex,
269 GetType().Name, methodName));
270
271 db.ExecuteDictionary(dictionary, mms[0].MemberName, objectType, null);
272 }
273
274 protected void ExecuteScalarDictionary(
275 DbManager db,
276 IDictionary dictionary,
277 Type objectType,
278 Type keyType,
279 string methodName,
280 NameOrIndexParameter scalarField,
281 Type elementType)
282 {
283 var isIndex = TypeHelper.IsSameOrParent(typeof(CompoundValue), keyType);
284 var mms = new SqlQuery(Extensions).GetKeyFieldList(db, objectType);
285
286 if (mms.Length == 0)
287 throw new DataAccessException(string.Format(
288 Resources.DataAccessor_UnknownIndex,
289 GetType().Name, methodName));
290
291 if (mms.Length > 1 && keyType != typeof(object) && !isIndex)
292 throw new DataAccessException(string.Format(
293 Resources.DataAccessor_InvalidKeyType,
294 GetType().Name, methodName));
295
296 if (isIndex || mms.Length > 1)
297 {
298 var fields = new string[mms.Length];
299
300 for (var i = 0; i < mms.Length; i++)
301 fields[i] = mms[i].Name;
302
303 db.ExecuteScalarDictionary(dictionary, new MapIndex(fields), scalarField, elementType);
304 }
305 else
306 {
307 db.ExecuteScalarDictionary(
308 dictionary,
309 mms[0].Name,
310 keyType,
311 scalarField,
312 elementType);
313 }
314 }
315
316 #endregion
317
318 #region ExecuteEnumerable
319
320 protected IEnumerable<T> ExecuteEnumerable<T>(DbManager db, Type objectType, bool disposeDbManager)
321 {
322 try
323 {
324 using (var rd = db.ExecuteReader())
325 {
326 if (rd.Read())
327 {
328 var dest = MappingSchema.GetObjectMapper(objectType);
329 var source = MappingSchema.CreateDataReaderMapper(rd);
330
331 var ctx = new InitContext
332 {
333 MappingSchema = MappingSchema,
334 ObjectMapper = dest,
335 DataSource = source,
336 SourceObject = rd
337 };
338
339 var index = MappingSchema.GetIndex(source, dest);
340 var mappers = ctx.MappingSchema.GetValueMappers(source, dest, index);
341
342 do
343 {
344 var destObject = (T)dest.CreateInstance(ctx);
345
346 if (ctx.StopMapping)
347 yield return destObject;
348
349 var smDest = destObject as ISupportMapping;
350
351 if (smDest != null)
352 {
353 smDest.BeginMapping(ctx);
354
355 if (ctx.StopMapping)
356 yield return destObject;
357 }
358
359 MappingSchema.MapInternal(source, rd, dest, destObject, index, mappers);
360
361 if (smDest != null)
362 smDest.EndMapping(ctx);
363
364 yield return destObject;
365 } while (rd.Read());
366 }
367 }
368 }
369 finally
370 {
371 if (disposeDbManager)
372 db.Dispose();
373 }
374 }
375
376 protected IEnumerable ExecuteEnumerable(DbManager db, Type objectType, bool disposeDbManager)
377 {
378 var ms = db.MappingSchema;
379
380 if (disposeDbManager)
381 {
382 using (db)
383 using (var rd = db.ExecuteReader())
384 while (rd.Read())
385 yield return ms.MapDataReaderToObject(rd, objectType);
386 }
387 else
388 {
389 using (var rd = db.ExecuteReader())
390 while (rd.Read())
391 yield return ms.MapDataReaderToObject(rd, objectType);
392 }
393 }
394
395 #endregion
396
397 #region Convert
398
399 #region Primitive Types
400
401 [CLSCompliant(false)]
402 [NoInterception]
403 protected virtual SByte ConvertToSByte(DbManager db, object value, object parameter)
404 {
405 return db.MappingSchema.ConvertToSByte(value);
406 }
407
408 [NoInterception]
409 protected virtual Int16 ConvertToInt16(DbManager db, object value, object parameter)
410 {
411 return db.MappingSchema.ConvertToInt16(value);
412 }
413
414 [NoInterception]
415 protected virtual Int32 ConvertToInt32(DbManager db, object value, object parameter)
416 {
417 return db.MappingSchema.ConvertToInt32(value);
418 }
419
420 [NoInterception]
421 protected virtual Int64 ConvertToInt64(DbManager db, object value, object parameter)
422 {
423 return db.MappingSchema.ConvertToInt64(value);
424 }
425
426 [NoInterception]
427 protected virtual Byte ConvertToByte(DbManager db, object value, object parameter)
428 {
429 return db.MappingSchema.ConvertToByte(value);
430 }
431
432 [CLSCompliant(false)]
433 [NoInterception]
434 protected virtual UInt16 ConvertToUInt16(DbManager db, object value, object parameter)
435 {
436 return db.MappingSchema.ConvertToUInt16(value);
437 }
438
439 [CLSCompliant(false)]
440 [NoInterception]
441 protected virtual UInt32 ConvertToUInt32(DbManager db, object value, object parameter)
442 {
443 return db.MappingSchema.ConvertToUInt32(value);
444 }
445
446 [CLSCompliant(false)]
447 [NoInterception]
448 protected virtual UInt64 ConvertToUInt64(DbManager db, object value, object parameter)
449 {
450 return db.MappingSchema.ConvertToUInt64(value);
451 }
452
453 [NoInterception]
454 protected virtual Char ConvertToChar(DbManager db, object value, object parameter)
455 {
456 return db.MappingSchema.ConvertToChar(value);
457 }
458
459 [NoInterception]
460 protected virtual Single ConvertToSingle(DbManager db, object value, object parameter)
461 {
462 return db.MappingSchema.ConvertToSingle(value);
463 }
464
465 [NoInterception]
466 protected virtual Double ConvertToDouble(DbManager db, object value, object parameter)
467 {
468 return db.MappingSchema.ConvertToDouble(value);
469 }
470
471 [NoInterception]
472 protected virtual Boolean ConvertToBoolean(DbManager db, object value, object parameter)
473 {
474 return db.MappingSchema.ConvertToBoolean(value);
475 }
476
477 #endregion
478
479 #region Simple Types
480
481 [NoInterception]
482 protected virtual String ConvertToString(DbManager db, object value, object parameter)
483 {
484 return db.MappingSchema.ConvertToString(value);
485 }
486
487 [NoInterception]
488 protected virtual DateTime ConvertToDateTime(DbManager db, object value, object parameter)
489 {
490 return db.MappingSchema.ConvertToDateTime(value);
491 }
492
493 [NoInterception]
494 protected virtual DateTimeOffset ConvertToDateTimeOffset(DbManager db, object value, object parameter)
495 {
496 return db.MappingSchema.ConvertToDateTimeOffset(value);
497 }
498
499 [NoInterception]
500 protected virtual System.Data.Linq.Binary ConvertToLinqBinary(DbManager db, object value, object parameter)
501 {
502 return db.MappingSchema.ConvertToLinqBinary(value);
503 }
504
505 [NoInterception]
506 protected virtual Decimal ConvertToDecimal(DbManager db, object value, object parameter)
507 {
508 return db.MappingSchema.ConvertToDecimal(value);
509 }
510
511 [NoInterception]
512 protected virtual Guid ConvertToGuid(DbManager db, object value, object parameter)
513 {
514 return db.MappingSchema.ConvertToGuid(value);
515 }
516
517 [NoInterception]
518 protected virtual Stream ConvertToStream(DbManager db, object value, object parameter)
519 {
520 return db.MappingSchema.ConvertToStream(value);
521 }
522
523 [NoInterception]
524 protected virtual XmlReader ConvertToXmlReader(DbManager db, object value, object parameter)
525 {
526 return db.MappingSchema.ConvertToXmlReader(value);
527 }
528
529 [NoInterception]
530 protected virtual XmlDocument ConvertToXmlDocument(DbManager db, object value, object parameter)
531 {
532 return db.MappingSchema.ConvertToXmlDocument(value);
533 }
534
535 #if !SILVERLIGHT
536 [NoInterception]
537 protected virtual XElement ConvertToXElement(DbManager db, object value, object parameter)
538 {
539 return db.MappingSchema.ConvertToXElement(value);
540 }
541 #endif
542
543 [NoInterception]
544 protected virtual Byte[] ConvertToByteArray(DbManager db, object value, object parameter)
545 {
546 return db.MappingSchema.ConvertToByteArray(value);
547 }
548
549 [NoInterception]
550 protected virtual Char[] ConvertToCharArray(DbManager db, object value, object parameter)
551 {
552 return db.MappingSchema.ConvertToCharArray(value);
553 }
554
555 #endregion
556
557 #region SqlTypes
558
559 [NoInterception]
560 protected virtual SqlByte ConvertToSqlByte(DbManager db, object value, object parameter)
561 {
562 return db.MappingSchema.ConvertToSqlByte(value);
563 }
564
565 [NoInterception]
566 protected virtual SqlInt16 ConvertToSqlInt16(DbManager db, object value, object parameter)
567 {
568 return db.MappingSchema.ConvertToSqlInt16(value);
569 }
570
571 [NoInterception]
572 protected virtual SqlInt32 ConvertToSqlInt32(DbManager db, object value, object parameter)
573 {
574 return db.MappingSchema.ConvertToSqlInt32(value);
575 }
576
577 [NoInterception]
578 protected virtual SqlInt64 ConvertToSqlInt64(DbManager db, object value, object parameter)
579 {
580 return db.MappingSchema.ConvertToSqlInt64(value);
581 }
582
583 [NoInterception]
584 protected virtual SqlSingle ConvertToSqlSingle(DbManager db, object value, object parameter)
585 {
586 return db.MappingSchema.ConvertToSqlSingle(value);
587 }
588
589 [NoInterception]
590 protected virtual SqlBoolean ConvertToSqlBoolean(DbManager db, object value, object parameter)
591 {
592 return db.MappingSchema.ConvertToSqlBoolean(value);
593 }
594
595 [NoInterception]
596 protected virtual SqlDouble ConvertToSqlDouble(DbManager db, object value, object parameter)
597 {
598 return db.MappingSchema.ConvertToSqlDouble(value);
599 }
600
601 [NoInterception]
602 protected virtual SqlDateTime ConvertToSqlDateTime(DbManager db, object value, object parameter)
603 {
604 return db.MappingSchema.ConvertToSqlDateTime(value);
605 }
606
607 [NoInterception]
608 protected virtual SqlDecimal ConvertToSqlDecimal(DbManager db, object value, object parameter)
609 {
610 return db.MappingSchema.ConvertToSqlDecimal(value);
611 }
612
613 [NoInterception]
614 protected virtual SqlMoney ConvertToSqlMoney(DbManager db, object value, object parameter)
615 {
616 return db.MappingSchema.ConvertToSqlMoney(value);
617 }
618
619 [NoInterception]
620 protected virtual SqlGuid ConvertToSqlGuid(DbManager db, object value, object parameter)
621 {
622 return db.MappingSchema.ConvertToSqlGuid(value);
623 }
624
625 [NoInterception]
626 protected virtual SqlString ConvertToSqlString(DbManager db, object value, object parameter)
627 {
628 return db.MappingSchema.ConvertToSqlString(value);
629 }
630
631 #endregion
632
633 #region General case
634
635 [NoInterception]
636 protected virtual object ConvertChangeType(
637 DbManager db,
638 object value,
639 Type conversionType,
640 object parameter)
641 {
642 return db.MappingSchema.ConvertChangeType(value, conversionType);
643 }
644
645 #endregion
646
647 #endregion
648
649 #region IsNull
650
651 /// <summary>
652 /// Reserved for internal BLToolkit use.
653 /// </summary>
654 public interface INullableInternal
655 {
656 bool IsNull { [MustImplement(false, false)] get; }
657 }
658
659 [NoInterception]
660 protected virtual bool IsNull(
661 DbManager db,
662 object value,
663 object parameter)
664 {
665 // Speed up for scalar and nullable types.
666 //
667 switch (System.Convert.GetTypeCode(value))
668 {
669 // null, DBNull.Value, Nullable<T> without a value.
670 //
671 case TypeCode.Empty:
672 case TypeCode.DBNull:
673 return true;
674
675 case TypeCode.Object:
676 break;
677
678 // int, byte, string, DateTime and other primitives except Guid.
679 // Also Nullable<T> with a value.
680 //
681 default:
682 return false;
683 }
684
685 // Speed up for SqlTypes.
686 //
687 var nullable = value as INullable;
688 if (nullable != null)
689 return nullable.IsNull;
690
691 // All other types which have 'IsNull' property but does not implement 'INullable' interface.
692 // For example: 'Oracle.DataAccess.Types.OracleDecimal'.
693 //
694 // For types without 'IsNull' property the return value is always false.
695 //
696 var nullableInternal = (INullableInternal)DuckTyping.Implement(typeof(INullableInternal), value);
697
698 return nullableInternal.IsNull;
699 }
700
701 #endregion
702
703 protected virtual SqlQueryAttribute GetSqlQueryAttribute(MethodInfo methodInfo)
704 {
705 var attrs = methodInfo.GetCustomAttributes(typeof(SqlQueryAttribute), true);
706 return (SqlQueryAttribute)attrs[0];
707 }
708
709 #endregion
710 }
711 }