comparison Source/Data/DataProvider/OdpDataProvider.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 // Odp.Net Data Provider.
2 // http://www.oracle.com/technology/tech/windows/odpnet/index.html
3 //
4 using System;
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.Data;
8 using System.Data.Common;
9 using System.Globalization;
10 using System.IO;
11 using System.Linq;
12 using System.Reflection;
13 using System.Text;
14 using System.Xml;
15
16 using BLToolkit.Aspects;
17 using BLToolkit.Common;
18 using BLToolkit.Mapping;
19 using BLToolkit.Reflection;
20
21 #if MANAGED
22 using Oracle.ManagedDataAccess.Client;
23 using Oracle.ManagedDataAccess.Types;
24 #else
25 using Oracle.DataAccess.Client;
26 using Oracle.DataAccess.Types;
27 #endif
28
29 namespace BLToolkit.Data.DataProvider
30 {
31 using Sql.SqlProvider;
32 using BLToolkit.Data.Sql;
33
34 /// <summary>
35 /// Implements access to the Data Provider for Oracle.
36 /// </summary>
37 /// <remarks>
38 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
39 /// </remarks>
40 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
41 #if !MANAGED
42 public class OdpDataProvider : DataProviderBase
43 {
44 public OdpDataProvider()
45 {
46 MappingSchema = new OdpMappingSchema();
47 }
48
49 public const string NameString = DataProvider.ProviderName.Oracle;
50
51 private const string DbTypeTableName = "Oracle.DataAccess.Client.OraDb_DbTypeTable";
52
53 static OdpDataProvider()
54 {
55 #else
56 public class OdpManagedDataProvider : DataProviderBase
57 {
58 public OdpManagedDataProvider()
59 {
60 MappingSchema = new OdpMappingSchema();
61 }
62
63 public const string NameString = DataProvider.ProviderName.OracleManaged;
64
65 private const string DbTypeTableName = "Oracle.ManagedDataAccess.Client.OraDb_DbTypeTable";
66
67 static OdpManagedDataProvider()
68 {
69 #endif
70 // Fix Oracle.Net bug #1: Array types are not handled.
71 //
72 var oraDbDbTypeTableType = typeof(OracleParameter).Assembly.GetType(DbTypeTableName);
73
74 if (null != oraDbDbTypeTableType)
75 {
76 var typeTable = (Hashtable)oraDbDbTypeTableType.InvokeMember(
77 "s_table", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField,
78 null, null, Type.EmptyTypes);
79
80 if (null != typeTable)
81 {
82 typeTable[typeof(DateTime[])] = OracleDbType.TimeStamp;
83 typeTable[typeof(Int16[])] = OracleDbType.Int16;
84 typeTable[typeof(Int32[])] = OracleDbType.Int32;
85 typeTable[typeof(Int64[])] = OracleDbType.Int64;
86 typeTable[typeof(Single[])] = OracleDbType.Single;
87 typeTable[typeof(Double[])] = OracleDbType.Double;
88 typeTable[typeof(Decimal[])] = OracleDbType.Decimal;
89 typeTable[typeof(TimeSpan[])] = OracleDbType.IntervalDS;
90 typeTable[typeof(String[])] = OracleDbType.Varchar2;
91 typeTable[typeof(OracleBFile[])] = OracleDbType.BFile;
92 typeTable[typeof(OracleBinary[])] = OracleDbType.Raw;
93 typeTable[typeof(OracleBlob[])] = OracleDbType.Blob;
94 typeTable[typeof(OracleClob[])] = OracleDbType.Clob;
95 typeTable[typeof(OracleDate[])] = OracleDbType.Date;
96 typeTable[typeof(OracleDecimal[])] = OracleDbType.Decimal;
97 typeTable[typeof(OracleIntervalDS[])] = OracleDbType.IntervalDS;
98 typeTable[typeof(OracleIntervalYM[])] = OracleDbType.IntervalYM;
99 typeTable[typeof(OracleRefCursor[])] = OracleDbType.RefCursor;
100 typeTable[typeof(OracleString[])] = OracleDbType.Varchar2;
101 typeTable[typeof(OracleTimeStamp[])] = OracleDbType.TimeStamp;
102 typeTable[typeof(OracleTimeStampLTZ[])]= OracleDbType.TimeStampLTZ;
103 typeTable[typeof(OracleTimeStampTZ[])] = OracleDbType.TimeStampTZ;
104 #if !MANAGED
105 typeTable[typeof(OracleXmlType[])] = OracleDbType.XmlType;
106 #endif
107
108 typeTable[typeof(Boolean)] = OracleDbType.Byte;
109 typeTable[typeof(Guid)] = OracleDbType.Raw;
110 typeTable[typeof(SByte)] = OracleDbType.Decimal;
111 typeTable[typeof(UInt16)] = OracleDbType.Decimal;
112 typeTable[typeof(UInt32)] = OracleDbType.Decimal;
113 typeTable[typeof(UInt64)] = OracleDbType.Decimal;
114
115 typeTable[typeof(Boolean[])] = OracleDbType.Byte;
116 typeTable[typeof(Guid[])] = OracleDbType.Raw;
117 typeTable[typeof(SByte[])] = OracleDbType.Decimal;
118 typeTable[typeof(UInt16[])] = OracleDbType.Decimal;
119 typeTable[typeof(UInt32[])] = OracleDbType.Decimal;
120 typeTable[typeof(UInt64[])] = OracleDbType.Decimal;
121
122 typeTable[typeof(Boolean?)] = OracleDbType.Byte;
123 typeTable[typeof(Guid?)] = OracleDbType.Raw;
124 typeTable[typeof(SByte?)] = OracleDbType.Decimal;
125 typeTable[typeof(UInt16?)] = OracleDbType.Decimal;
126 typeTable[typeof(UInt32?)] = OracleDbType.Decimal;
127 typeTable[typeof(UInt64?)] = OracleDbType.Decimal;
128 typeTable[typeof(DateTime?[])] = OracleDbType.TimeStamp;
129 typeTable[typeof(Int16?[])] = OracleDbType.Int16;
130 typeTable[typeof(Int32?[])] = OracleDbType.Int32;
131 typeTable[typeof(Int64?[])] = OracleDbType.Int64;
132 typeTable[typeof(Single?[])] = OracleDbType.Single;
133 typeTable[typeof(Double?[])] = OracleDbType.Double;
134 typeTable[typeof(Decimal?[])] = OracleDbType.Decimal;
135 typeTable[typeof(TimeSpan?[])] = OracleDbType.IntervalDS;
136 typeTable[typeof(Boolean?[])] = OracleDbType.Byte;
137 typeTable[typeof(Guid?[])] = OracleDbType.Raw;
138 typeTable[typeof(SByte?[])] = OracleDbType.Decimal;
139 typeTable[typeof(UInt16?[])] = OracleDbType.Decimal;
140 typeTable[typeof(UInt32?[])] = OracleDbType.Decimal;
141 typeTable[typeof(UInt64?[])] = OracleDbType.Decimal;
142
143 typeTable[typeof(XmlReader)] = OracleDbType.XmlType;
144 typeTable[typeof(XmlDocument)] = OracleDbType.XmlType;
145 typeTable[typeof(MemoryStream)] = OracleDbType.Blob;
146 typeTable[typeof(XmlReader[])] = OracleDbType.XmlType;
147 typeTable[typeof(XmlDocument[])] = OracleDbType.XmlType;
148 typeTable[typeof(MemoryStream[])] = OracleDbType.Blob;
149 }
150 }
151 }
152
153 /// <summary>
154 /// Creates the database connection object.
155 /// </summary>
156 /// <remarks>
157 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
158 /// </remarks>
159 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
160 /// <returns>The database connection object.</returns>
161 public override IDbConnection CreateConnectionObject()
162 {
163 return new OracleConnection();
164 }
165
166 public override IDbCommand CreateCommandObject(IDbConnection connection)
167 {
168 var oraConnection = connection as OracleConnection;
169
170 if (null != oraConnection)
171 {
172 var oraCommand = oraConnection.CreateCommand();
173
174 // Fix Oracle.Net bug #2: Empty arrays can not be sent to the server.
175 //
176 oraCommand.BindByName = true;
177
178 return oraCommand;
179 }
180
181 return base.CreateCommandObject(connection);
182 }
183
184 public override void SetParameterValue(IDbDataParameter parameter, object value)
185 {
186 base.SetParameterValue(parameter, value);
187
188 // strings and byte arrays larger than 4000 bytes may be handled improperly
189 if (parameter is OracleParameterWrap)
190 {
191 const int ThresholdSize = 4000;
192 if (value is string && Encoding.UTF8.GetBytes((string)value).Length > ThresholdSize)
193 {
194 ((OracleParameterWrap)parameter).OracleParameter.OracleDbType = OracleDbType.Clob;
195 }
196 else if (value is byte[] && ((byte[])value).Length > ThresholdSize)
197 {
198 ((OracleParameterWrap)parameter).OracleParameter.OracleDbType = OracleDbType.Blob;
199 }
200 }
201 }
202
203 public override IDbDataParameter CloneParameter(IDbDataParameter parameter)
204 {
205 var oraParameter = (parameter is OracleParameterWrap)?
206 (parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
207
208 if (null != oraParameter)
209 {
210 var oraParameterClone = (OracleParameter)oraParameter.Clone();
211
212 // Fix Oracle.Net bug #3: CollectionType property is not cloned.
213 //
214 oraParameterClone.CollectionType = oraParameter.CollectionType;
215
216 // Fix Oracle.Net bug #8423178
217 // See http://forums.oracle.com/forums/thread.jspa?threadID=975902&tstart=0
218 //
219 if (oraParameterClone.OracleDbType == OracleDbType.RefCursor)
220 {
221 // Set OracleDbType to itself to reset m_bSetDbType and m_bOracleDbTypeExSet
222 //
223 oraParameterClone.OracleDbType = OracleDbType.RefCursor;
224 }
225
226 return OracleParameterWrap.CreateInstance(oraParameterClone);
227 }
228
229 return base.CloneParameter(parameter);
230 }
231
232 public override void SetUserDefinedType(IDbDataParameter parameter, string typeName)
233 {
234 var oraParameter = (parameter is OracleParameterWrap) ?
235 (parameter as OracleParameterWrap).OracleParameter : parameter as OracleParameter;
236
237 if (oraParameter == null)
238 throw new ArgumentException("OracleParameter expected.", "parameter");
239
240 oraParameter.UdtTypeName = typeName;
241 }
242
243 /// <summary>
244 /// Creates the data adapter object.
245 /// </summary>
246 /// <remarks>
247 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
248 /// </remarks>
249 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
250 /// <returns>A data adapter object.</returns>
251 public override DbDataAdapter CreateDataAdapterObject()
252 {
253 return new OracleDataAdapter();
254 }
255
256 /// <summary>
257 /// Populates the specified IDbCommand object's Parameters collection with
258 /// parameter information for the stored procedure specified in the IDbCommand.
259 /// </summary>
260 /// <remarks>
261 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
262 /// </remarks>
263 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
264 /// <param name="command">The IDbCommand referencing the stored procedure for which the parameter
265 /// information is to be derived. The derived parameters will be populated into
266 /// the Parameters of this command.</param>
267 public override bool DeriveParameters(IDbCommand command)
268 {
269 var oraCommand = command as OracleCommand;
270
271 if (null != oraCommand)
272 {
273 try
274 {
275 OracleCommandBuilder.DeriveParameters(oraCommand);
276 }
277 catch (Exception ex)
278 {
279 // Make Oracle less laconic.
280 //
281 throw new DataException(string.Format("{0}\nCommandText: {1}", ex.Message, oraCommand.CommandText), ex);
282 }
283
284 return true;
285 }
286
287 return false;
288 }
289
290 /// <summary>
291 /// Open an <see cref="IDataReader"/> into the given <see cref="OracleRefCursor"/> object
292 /// </summary>
293 /// <param name="refCursor">an <see cref="OracleRefCursor"/> to perform GetDataReader() on</param>
294 /// <returns>The <see cref="IDataReader"/> into the returned by GetDataReader()</returns>
295 public override IDataReader GetRefCursorDataReader(object refCursor)
296 {
297 var oracleRefCursor = refCursor as OracleRefCursor;
298
299 if (oracleRefCursor == null)
300 throw new ArgumentException("Argument must be of type 'OracleRefCursor'", "refCursor");
301
302 return oracleRefCursor.GetDataReader();
303 }
304
305 public override object Convert(object value, ConvertType convertType)
306 {
307 switch (convertType)
308 {
309 case ConvertType.NameToCommandParameter:
310 case ConvertType.NameToSprocParameter:
311 return ParameterPrefix == null? value: ParameterPrefix + value;
312
313 case ConvertType.SprocParameterToName:
314 var name = (string)value;
315
316 if (name.Length > 0)
317 {
318 if (name[0] == ':')
319 return name.Substring(1);
320
321 if (ParameterPrefix != null &&
322 name.ToUpper(CultureInfo.InvariantCulture).StartsWith(ParameterPrefix))
323 {
324 return name.Substring(ParameterPrefix.Length);
325 }
326 }
327
328 break;
329
330 case ConvertType.ExceptionToErrorNumber:
331 if (value is OracleException)
332 return ((OracleException)value).Number;
333 break;
334 }
335
336 return SqlProvider.Convert(value, convertType);
337 }
338
339 public override void PrepareCommand(ref CommandType commandType, ref string commandText, ref IDbDataParameter[] commandParameters)
340 {
341 base.PrepareCommand(ref commandType, ref commandText, ref commandParameters);
342
343 if (commandType == CommandType.Text)
344 {
345 // Fix Oracle bug #11 '\r' is not a valid character!
346 //
347 commandText = commandText.Replace('\r', ' ');
348 }
349 }
350
351 public override void AttachParameter(IDbCommand command, IDbDataParameter parameter)
352 {
353 var oraParameter = (parameter is OracleParameterWrap)?
354 (parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
355
356 if (null != oraParameter)
357 {
358 if (oraParameter.CollectionType == OracleCollectionType.PLSQLAssociativeArray)
359 {
360 if (oraParameter.Direction == ParameterDirection.Input
361 || oraParameter.Direction == ParameterDirection.InputOutput)
362 {
363 var ar = oraParameter.Value as Array;
364
365 if (null != ar && !(ar is byte[] || ar is char[]))
366 {
367 oraParameter.Size = ar.Length;
368
369 if (oraParameter.DbType == DbType.String
370 && oraParameter.Direction == ParameterDirection.InputOutput)
371 {
372 var arrayBindSize = new int[oraParameter.Size];
373
374 for (var i = 0; i < oraParameter.Size; ++i)
375 {
376 arrayBindSize[i] = 1024;
377 }
378
379 oraParameter.ArrayBindSize = arrayBindSize;
380 }
381 }
382
383 if (oraParameter.Size == 0)
384 {
385 // Skip this parameter.
386 // Fix Oracle.Net bug #2: Empty arrays can not be sent to the server.
387 //
388 return;
389 }
390
391 if (oraParameter.Value is Stream[])
392 {
393 var streams = (Stream[]) oraParameter.Value;
394
395 for (var i = 0; i < oraParameter.Size; ++i)
396 {
397 if (streams[i] is OracleBFile || streams[i] is OracleBlob || streams[i] is OracleClob
398 #if !MANAGED
399 || streams[i] is OracleXmlStream
400 #endif
401 )
402 {
403 // Known Oracle type.
404 //
405 continue;
406 }
407
408 streams[i] = CopyStream(streams[i], (OracleCommand)command);
409 }
410 }
411 else if (oraParameter.Value is XmlDocument[])
412 {
413 var xmlDocuments = (XmlDocument[]) oraParameter.Value;
414 var values = new object[oraParameter.Size];
415
416 switch (oraParameter.OracleDbType)
417 {
418 case OracleDbType.XmlType:
419 #if !MANAGED
420 for (var i = 0; i < oraParameter.Size; ++i)
421 {
422 values[i] = xmlDocuments[i].DocumentElement == null?
423 (object) DBNull.Value:
424 new OracleXmlType((OracleConnection)command.Connection, xmlDocuments[i]);
425 }
426
427 oraParameter.Value = values;
428 break;
429 #else
430 throw new NotSupportedException();
431 #endif
432 // Fix Oracle.Net bug #9: XmlDocument.ToString() returns System.Xml.XmlDocument,
433 // so m_value.ToString() is not enought.
434 //
435 case OracleDbType.Clob:
436 case OracleDbType.NClob:
437 case OracleDbType.Varchar2:
438 case OracleDbType.NVarchar2:
439 case OracleDbType.Char:
440 case OracleDbType.NChar:
441 for (var i = 0; i < oraParameter.Size; ++i)
442 {
443 values[i] = xmlDocuments[i].DocumentElement == null?
444 (object) DBNull.Value:
445 xmlDocuments[i].InnerXml;
446 }
447
448 oraParameter.Value = values;
449
450 break;
451
452 // Or convert to bytes if need.
453 //
454 case OracleDbType.Blob:
455 case OracleDbType.BFile:
456 case OracleDbType.Raw:
457 case OracleDbType.Long:
458 case OracleDbType.LongRaw:
459 for (var i = 0; i < oraParameter.Size; ++i)
460 {
461 if (xmlDocuments[i].DocumentElement == null)
462 values[i] = DBNull.Value;
463 else
464 using (var s = new MemoryStream())
465 {
466 xmlDocuments[i].Save(s);
467 values[i] = s.GetBuffer();
468 }
469 }
470
471 oraParameter.Value = values;
472
473 break;
474 }
475 }
476 }
477 else if (oraParameter.Direction == ParameterDirection.Output)
478 {
479 // Fix Oracle.Net bug #4: ArrayBindSize must be explicitly specified.
480 //
481 if (oraParameter.DbType == DbType.String)
482 {
483 oraParameter.Size = 1024;
484 var arrayBindSize = new int[oraParameter.Size];
485 for (var i = 0; i < oraParameter.Size; ++i)
486 {
487 arrayBindSize[i] = 1024;
488 }
489
490 oraParameter.ArrayBindSize = arrayBindSize;
491 }
492 else
493 {
494 oraParameter.Size = 32767;
495 }
496 }
497 }
498 else if (oraParameter.Value is Stream)
499 {
500 var stream = (Stream) oraParameter.Value;
501
502 if (!(stream is OracleBFile) && !(stream is OracleBlob) &&
503 !(stream is OracleClob)
504 #if !MANAGED
505 && !(stream is OracleXmlStream)
506 #endif
507 )
508 {
509 oraParameter.Value = CopyStream(stream, (OracleCommand)command);
510 }
511 }
512 else if (oraParameter.Value is Byte[])
513 {
514 var bytes = (Byte[]) oraParameter.Value;
515
516 if (bytes.Length > 32000)
517 {
518 oraParameter.Value = CopyStream(bytes, (OracleCommand)command);
519 }
520 }
521 else if (oraParameter.Value is XmlDocument)
522 {
523 var xmlDocument = (XmlDocument)oraParameter.Value;
524 if (xmlDocument.DocumentElement == null)
525 oraParameter.Value = DBNull.Value;
526 else
527 {
528
529 switch (oraParameter.OracleDbType)
530 {
531 case OracleDbType.XmlType:
532 #if !MANAGED
533 oraParameter.Value = new OracleXmlType((OracleConnection)command.Connection, xmlDocument);
534 break;
535 #else
536 throw new NotSupportedException();
537 #endif
538
539 // Fix Oracle.Net bug #9: XmlDocument.ToString() returns System.Xml.XmlDocument,
540 // so m_value.ToString() is not enought.
541 //
542 case OracleDbType.Clob:
543 case OracleDbType.NClob:
544 case OracleDbType.Varchar2:
545 case OracleDbType.NVarchar2:
546 case OracleDbType.Char:
547 case OracleDbType.NChar:
548 using (TextWriter w = new StringWriter())
549 {
550 xmlDocument.Save(w);
551 oraParameter.Value = w.ToString();
552 }
553 break;
554
555 // Or convert to bytes if need.
556 //
557 case OracleDbType.Blob:
558 case OracleDbType.BFile:
559 case OracleDbType.Raw:
560 case OracleDbType.Long:
561 case OracleDbType.LongRaw:
562 using (var s = new MemoryStream())
563 {
564 xmlDocument.Save(s);
565 oraParameter.Value = s.GetBuffer();
566 }
567 break;
568 }
569 }
570 }
571
572 parameter = oraParameter;
573 }
574
575 base.AttachParameter(command, parameter);
576 }
577
578 private static Stream CopyStream(Stream stream, OracleCommand cmd)
579 {
580 return CopyStream(Common.Convert.ToByteArray(stream), cmd);
581 }
582
583 private static Stream CopyStream(Byte[] bytes, OracleCommand cmd)
584 {
585 var ret = new OracleBlob(cmd.Connection);
586 ret.Write(bytes, 0, bytes.Length);
587 return ret;
588 }
589
590 public override bool IsValueParameter(IDbDataParameter parameter)
591 {
592 var oraParameter = (parameter is OracleParameterWrap)?
593 (parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
594
595 if (null != oraParameter)
596 {
597 if (oraParameter.OracleDbType == OracleDbType.RefCursor
598 && oraParameter.Direction == ParameterDirection.Output)
599 {
600 // Ignore out ref cursors, while out parameters of other types are o.k.
601 return false;
602 }
603 }
604
605 return base.IsValueParameter(parameter);
606 }
607
608 public override IDbDataParameter CreateParameterObject(IDbCommand command)
609 {
610 var parameter = base.CreateParameterObject(command);
611
612 if (parameter is OracleParameter)
613 parameter = OracleParameterWrap.CreateInstance(parameter as OracleParameter);
614
615 return parameter;
616 }
617
618 public override IDbDataParameter GetParameter(IDbCommand command, NameOrIndexParameter nameOrIndex)
619 {
620 var parameter = base.GetParameter(command, nameOrIndex);
621
622 if (parameter is OracleParameter)
623 parameter = OracleParameterWrap.CreateInstance(parameter as OracleParameter);
624
625 return parameter;
626 }
627
628 /// <summary>
629 /// Returns connection type.
630 /// </summary>
631 /// <remarks>
632 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
633 /// </remarks>
634 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
635 /// <value>An instance of the <see cref="Type"/> class.</value>
636 public override Type ConnectionType
637 {
638 get { return typeof(OracleConnection); }
639 }
640
641 /// <summary>
642 /// Returns the data provider name.
643 /// </summary>
644 /// <remarks>
645 /// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
646 /// </remarks>
647 /// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataProvider Method</seealso>
648 /// <value>Data provider name.</value>
649 public override string Name
650 {
651 get { return NameString; }
652 }
653
654 public override int MaxBatchSize
655 {
656 get { return 0; }
657 }
658
659 public override int ExecuteArray(IDbCommand command, int iterations)
660 {
661 var cmd = (OracleCommand)command;
662 var oracleParameters = cmd.Parameters.OfType<OracleParameter>().ToArray();
663 var oldCollectionTypes = oracleParameters.Select(p => p.CollectionType).ToArray();
664
665 try
666 {
667 foreach (var p in oracleParameters)
668 {
669 p.CollectionType = OracleCollectionType.None;
670 }
671
672 cmd.ArrayBindCount = iterations;
673 return cmd.ExecuteNonQuery();
674 }
675 finally
676 {
677 foreach (var p in oracleParameters.Zip(oldCollectionTypes, (p, t) => new { Param = p, CollectionType = t }))
678 {
679 p.Param.CollectionType = p.CollectionType;
680 }
681
682 cmd.ArrayBindCount = 0;
683 }
684 }
685
686 public override ISqlProvider CreateSqlProvider()
687 {
688 return new OracleSqlProvider();
689 }
690
691 public override IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader)
692 {
693 return dataReader is OracleDataReader ?
694 new OracleDataReaderEx((OracleDataReader)dataReader) :
695 base.GetDataReader(schema, dataReader);
696 }
697
698 class OracleDataReaderEx: DataReaderEx<OracleDataReader>
699 {
700 public OracleDataReaderEx(OracleDataReader rd)
701 : base(rd)
702 {
703 }
704
705 public override DateTimeOffset GetDateTimeOffset(int i)
706 {
707 var ts = DataReader.GetOracleTimeStampTZ(i);
708 return new DateTimeOffset(ts.Value, ts.GetTimeZoneOffset());
709 }
710 }
711
712 private string _parameterPrefix = "P";
713 public string ParameterPrefix
714 {
715 get { return _parameterPrefix; }
716 set
717 {
718 _parameterPrefix = string.IsNullOrEmpty(value)? null:
719 value.ToUpper(CultureInfo.InvariantCulture);
720 }
721 }
722
723 /// <summary>
724 /// One time initialization from a configuration file.
725 /// </summary>
726 /// <param name="attributes">Provider specific attributes.</param>
727 public override void Configure(System.Collections.Specialized.NameValueCollection attributes)
728 {
729 var val = attributes["ParameterPrefix"];
730 if (val != null)
731 ParameterPrefix = val;
732
733 base.Configure(attributes);
734 }
735
736 #region Inner types
737
738 public class OdpMappingSchema : MappingSchema
739 {
740 public override DataReaderMapper CreateDataReaderMapper(IDataReader dataReader)
741 {
742 return new OracleDataReaderMapper(this, dataReader);
743 }
744
745 public override DataReaderMapper CreateDataReaderMapper(
746 IDataReader dataReader,
747 NameOrIndexParameter nip)
748 {
749 return new OracleScalarDataReaderMapper(this, dataReader, nip);
750 }
751
752 public override Reflection.Extension.ExtensionList Extensions
753 {
754 get { return Map.DefaultSchema.Extensions; }
755 set { Map.DefaultSchema.Extensions = value; }
756 }
757
758 #region Convert
759
760 #region Primitive Types
761
762 [CLSCompliant(false)]
763 public override SByte ConvertToSByte(object value)
764 {
765 if (value is OracleDecimal)
766 {
767 var oraDecimal = (OracleDecimal)value;
768 return oraDecimal.IsNull? DefaultSByteNullValue: (SByte)oraDecimal.Value;
769 }
770
771 return base.ConvertToSByte(value);
772 }
773
774 public override Int16 ConvertToInt16(object value)
775 {
776 if (value is OracleDecimal)
777 {
778 var oraDecimal = (OracleDecimal)value;
779 return oraDecimal.IsNull? DefaultInt16NullValue: oraDecimal.ToInt16();
780 }
781
782 return base.ConvertToInt16(value);
783 }
784
785 public override Int32 ConvertToInt32(object value)
786 {
787 if (value is OracleDecimal)
788 {
789 var oraDecimal = (OracleDecimal)value;
790 return oraDecimal.IsNull? DefaultInt32NullValue: oraDecimal.ToInt32();
791 }
792
793 return base.ConvertToInt32(value);
794 }
795
796 public override Int64 ConvertToInt64(object value)
797 {
798 if (value is OracleDecimal)
799 {
800 var oraDecimal = (OracleDecimal)value;
801 return oraDecimal.IsNull? DefaultInt64NullValue: oraDecimal.ToInt64();
802 }
803
804 return base.ConvertToInt64(value);
805 }
806
807 public override Byte ConvertToByte(object value)
808 {
809 if (value is OracleDecimal)
810 {
811 var oraDecimal = (OracleDecimal)value;
812 return oraDecimal.IsNull? DefaultByteNullValue: oraDecimal.ToByte();
813 }
814
815 return base.ConvertToByte(value);
816 }
817
818 [CLSCompliant(false)]
819 public override UInt16 ConvertToUInt16(object value)
820 {
821 if (value is OracleDecimal)
822 {
823 var oraDecimal = (OracleDecimal)value;
824 return oraDecimal.IsNull? DefaultUInt16NullValue: (UInt16)oraDecimal.Value;
825 }
826
827 return base.ConvertToUInt16(value);
828 }
829
830 [CLSCompliant(false)]
831 public override UInt32 ConvertToUInt32(object value)
832 {
833 if (value is OracleDecimal)
834 {
835 var oraDecimal = (OracleDecimal)value;
836 return oraDecimal.IsNull? DefaultUInt32NullValue: (UInt32)oraDecimal.Value;
837 }
838
839 return base.ConvertToUInt32(value);
840 }
841
842 [CLSCompliant(false)]
843 public override UInt64 ConvertToUInt64(object value)
844 {
845 if (value is OracleDecimal)
846 {
847 var oraDecimal = (OracleDecimal)value;
848 return oraDecimal.IsNull? DefaultUInt64NullValue: (UInt64)oraDecimal.Value;
849 }
850
851 return base.ConvertToUInt64(value);
852 }
853
854 public override Single ConvertToSingle(object value)
855 {
856 if (value is OracleDecimal)
857 {
858 var oraDecimal = (OracleDecimal)value;
859 return oraDecimal.IsNull? DefaultSingleNullValue: oraDecimal.ToSingle();
860 }
861
862 return base.ConvertToSingle(value);
863 }
864
865 public override Double ConvertToDouble(object value)
866 {
867 if (value is OracleDecimal)
868 {
869 var oraDecimal = (OracleDecimal)value;
870 return oraDecimal.IsNull? DefaultDoubleNullValue: oraDecimal.ToDouble();
871 }
872
873 return base.ConvertToDouble(value);
874 }
875
876 public override Boolean ConvertToBoolean(object value)
877 {
878 if (value is OracleDecimal)
879 {
880 var oraDecimal = (OracleDecimal)value;
881 return oraDecimal.IsNull? DefaultBooleanNullValue: (oraDecimal.Value != 0);
882 }
883
884 return base.ConvertToBoolean(value);
885 }
886
887 public override DateTime ConvertToDateTime(object value)
888 {
889 if (value is OracleDate)
890 {
891 var oraDate = (OracleDate)value;
892 return oraDate.IsNull? DefaultDateTimeNullValue: oraDate.Value;
893 }
894
895 return base.ConvertToDateTime(value);
896 }
897
898 public override Decimal ConvertToDecimal(object value)
899 {
900 if (value is OracleDecimal)
901 {
902 var oraDecimal = (OracleDecimal)value;
903 return oraDecimal.IsNull? DefaultDecimalNullValue: oraDecimal.Value;
904 }
905
906 return base.ConvertToDecimal(value);
907 }
908
909 public override Guid ConvertToGuid(object value)
910 {
911 if (value is OracleString)
912 {
913 var oraString = (OracleString)value;
914 return oraString.IsNull? DefaultGuidNullValue: new Guid(oraString.Value);
915 }
916
917 if (value is OracleBlob)
918 {
919 using (var oraBlob = (OracleBlob)value)
920 return oraBlob.IsNull? DefaultGuidNullValue: new Guid(oraBlob.Value);
921 }
922
923 return base.ConvertToGuid(value);
924 }
925
926 public override String ConvertToString(object value)
927 {
928 if (value is OracleString)
929 {
930 var oraString = (OracleString)value;
931 return oraString.IsNull? DefaultStringNullValue: oraString.Value;
932 }
933 #if !MANAGED
934 if (value is OracleXmlType)
935 {
936 var oraXmlType = (OracleXmlType)value;
937 return oraXmlType.IsNull ? DefaultStringNullValue : oraXmlType.Value;
938 }
939 #endif
940 if (value is OracleClob)
941 {
942 using (var oraClob = (OracleClob)value)
943 return oraClob.IsNull? DefaultStringNullValue: oraClob.Value;
944 }
945
946 return base.ConvertToString(value);
947 }
948
949 #if !MANAGED
950 public override Stream ConvertToStream(object value)
951 {
952 if (value is OracleXmlType)
953 {
954 var oraXml = (OracleXmlType)value;
955 return oraXml.IsNull? DefaultStreamNullValue: oraXml.GetStream();
956 }
957
958 return base.ConvertToStream(value);
959 }
960
961 public override XmlReader ConvertToXmlReader(object value)
962 {
963 if (value is OracleXmlType)
964 {
965 var oraXml = (OracleXmlType)value;
966 return oraXml.IsNull? DefaultXmlReaderNullValue: oraXml.GetXmlReader();
967 }
968
969 return base.ConvertToXmlReader(value);
970 }
971
972 public override XmlDocument ConvertToXmlDocument(object value)
973 {
974 if (value is OracleXmlType)
975 {
976 var oraXml = (OracleXmlType)value;
977 return oraXml.IsNull? DefaultXmlDocumentNullValue: oraXml.GetXmlDocument();
978 }
979
980 return base.ConvertToXmlDocument(value);
981 }
982 #endif
983
984 public override Byte[] ConvertToByteArray(object value)
985 {
986 if (value is OracleBlob)
987 {
988 using (var oraBlob = (OracleBlob)value)
989 return oraBlob.IsNull? null: oraBlob.Value;
990 }
991
992 if (value is OracleBinary)
993 {
994 var oraBinary = (OracleBinary)value;
995 return oraBinary.IsNull? null: oraBinary.Value;
996 }
997
998 if (value is OracleBFile)
999 {
1000 var oraBFile = (OracleBFile)value;
1001 return oraBFile.IsNull? null: oraBFile.Value;
1002 }
1003
1004 return base.ConvertToByteArray(value);
1005 }
1006
1007 public override Char[] ConvertToCharArray(object value)
1008 {
1009 if (value is OracleString)
1010 {
1011 var oraString = (OracleString)value;
1012 return oraString.IsNull? null: oraString.Value.ToCharArray();
1013 }
1014
1015 if (value is OracleClob)
1016 {
1017 using (var oraClob = (OracleClob)value)
1018 return oraClob.IsNull? null: oraClob.Value.ToCharArray();
1019 }
1020
1021 return base.ConvertToCharArray(value);
1022 }
1023
1024 #endregion
1025
1026 #region Nullable Types
1027
1028 [CLSCompliant(false)]
1029 public override SByte? ConvertToNullableSByte(object value)
1030 {
1031 if (value is OracleDecimal)
1032 {
1033 var oraDecimal = (OracleDecimal)value;
1034 return oraDecimal.IsNull? null: (SByte?)oraDecimal.Value;
1035 }
1036
1037 return base.ConvertToNullableSByte(value);
1038 }
1039
1040 public override Int16? ConvertToNullableInt16(object value)
1041 {
1042 if (value is OracleDecimal)
1043 {
1044 var oraDecimal = (OracleDecimal)value;
1045 return oraDecimal.IsNull? null: (Int16?)oraDecimal.ToInt16();
1046 }
1047
1048 return base.ConvertToNullableInt16(value);
1049 }
1050
1051 public override Int32? ConvertToNullableInt32(object value)
1052 {
1053 if (value is OracleDecimal)
1054 {
1055 var oraDecimal = (OracleDecimal)value;
1056 return oraDecimal.IsNull? null: (Int32?)oraDecimal.ToInt32();
1057 }
1058
1059 return base.ConvertToNullableInt32(value);
1060 }
1061
1062 public override Int64? ConvertToNullableInt64(object value)
1063 {
1064 if (value is OracleDecimal)
1065 {
1066 var oraDecimal = (OracleDecimal)value;
1067 return oraDecimal.IsNull? null: (Int64?)oraDecimal.ToInt64();
1068 }
1069
1070 return base.ConvertToNullableInt64(value);
1071 }
1072
1073 public override Byte? ConvertToNullableByte(object value)
1074 {
1075 if (value is OracleDecimal)
1076 {
1077 var oraDecimal = (OracleDecimal)value;
1078 return oraDecimal.IsNull? null: (Byte?)oraDecimal.ToByte();
1079 }
1080
1081 return base.ConvertToNullableByte(value);
1082 }
1083
1084 [CLSCompliant(false)]
1085 public override UInt16? ConvertToNullableUInt16(object value)
1086 {
1087 if (value is OracleDecimal)
1088 {
1089 var oraDecimal = (OracleDecimal)value;
1090 return oraDecimal.IsNull? null: (UInt16?)oraDecimal.Value;
1091 }
1092
1093 return base.ConvertToNullableUInt16(value);
1094 }
1095
1096 [CLSCompliant(false)]
1097 public override UInt32? ConvertToNullableUInt32(object value)
1098 {
1099 if (value is OracleDecimal)
1100 {
1101 var oraDecimal = (OracleDecimal)value;
1102 return oraDecimal.IsNull? null: (UInt32?)oraDecimal.Value;
1103 }
1104
1105 return base.ConvertToNullableUInt32(value);
1106 }
1107
1108 [CLSCompliant(false)]
1109 public override UInt64? ConvertToNullableUInt64(object value)
1110 {
1111 if (value is OracleDecimal)
1112 {
1113 var oraDecimal = (OracleDecimal)value;
1114 return oraDecimal.IsNull? null: (UInt64?)oraDecimal.Value;
1115 }
1116
1117 return base.ConvertToNullableUInt64(value);
1118 }
1119
1120 public override Single? ConvertToNullableSingle(object value)
1121 {
1122 if (value is OracleDecimal)
1123 {
1124 var oraDecimal = (OracleDecimal)value;
1125 return oraDecimal.IsNull? null: (Single?)oraDecimal.ToSingle();
1126 }
1127
1128 return base.ConvertToNullableSingle(value);
1129 }
1130
1131 public override Double? ConvertToNullableDouble(object value)
1132 {
1133 if (value is OracleDecimal)
1134 {
1135 var oraDecimal = (OracleDecimal)value;
1136 return oraDecimal.IsNull? null: (Double?)oraDecimal.ToDouble();
1137 }
1138
1139 return base.ConvertToNullableDouble(value);
1140 }
1141
1142 public override Boolean? ConvertToNullableBoolean(object value)
1143 {
1144 if (value is OracleDecimal)
1145 {
1146 var oraDecimal = (OracleDecimal)value;
1147 return oraDecimal.IsNull? null: (Boolean?)(oraDecimal.Value != 0);
1148 }
1149
1150 return base.ConvertToNullableBoolean(value);
1151 }
1152
1153 public override DateTime? ConvertToNullableDateTime(object value)
1154 {
1155 if (value is OracleDate)
1156 {
1157 var oraDate = (OracleDate)value;
1158 return oraDate.IsNull? null: (DateTime?)oraDate.Value;
1159 }
1160
1161 return base.ConvertToNullableDateTime(value);
1162 }
1163
1164 public override Decimal? ConvertToNullableDecimal(object value)
1165 {
1166 if (value is OracleDecimal)
1167 {
1168 var oraDecimal = (OracleDecimal)value;
1169 return oraDecimal.IsNull? null: (Decimal?)oraDecimal.Value;
1170 }
1171
1172 return base.ConvertToNullableDecimal(value);
1173 }
1174
1175 public override Guid? ConvertToNullableGuid(object value)
1176 {
1177 if (value is OracleString)
1178 {
1179 var oraString = (OracleString)value;
1180 return oraString.IsNull? null: (Guid?)new Guid(oraString.Value);
1181 }
1182
1183 if (value is OracleBlob)
1184 {
1185 using (var oraBlob = (OracleBlob)value)
1186 return oraBlob.IsNull? null: (Guid?)new Guid(oraBlob.Value);
1187 }
1188
1189 return base.ConvertToNullableGuid(value);
1190 }
1191
1192 #endregion
1193
1194 #endregion
1195
1196 public override object MapValueToEnum(object value, Type type)
1197 {
1198 if (value is OracleString)
1199 {
1200 var oracleValue = (OracleString)value;
1201 value = oracleValue.IsNull? null: oracleValue.Value;
1202 }
1203 else if (value is OracleDecimal)
1204 {
1205 var oracleValue = (OracleDecimal)value;
1206 if (oracleValue.IsNull)
1207 value = null;
1208 else
1209 value = oracleValue.Value;
1210 }
1211
1212 return base.MapValueToEnum(value, type);
1213 }
1214
1215 public override object MapValueToEnum(object value, MemberAccessor ma)
1216 {
1217 if (value is OracleString)
1218 {
1219 var oracleValue = (OracleString)value;
1220 value = oracleValue.IsNull ? null : oracleValue.Value;
1221 }
1222 else if (value is OracleDecimal)
1223 {
1224 var oracleValue = (OracleDecimal)value;
1225 if (oracleValue.IsNull)
1226 value = null;
1227 else
1228 value = oracleValue.Value;
1229 }
1230
1231 return base.MapValueToEnum(value, ma);
1232 }
1233
1234 public override object ConvertChangeType(object value, Type conversionType)
1235 {
1236 // Handle OracleDecimal with IsNull == true case
1237 //
1238 return base.ConvertChangeType(IsNull(value)? null: value, conversionType);
1239 }
1240
1241 public override bool IsNull(object value)
1242 {
1243 // ODP 10 does not expose this interface to public.
1244 //
1245 // return value is INullable && ((INullable)value).IsNull;
1246
1247 return
1248 value is OracleDecimal? ((OracleDecimal) value).IsNull:
1249 value is OracleString? ((OracleString) value).IsNull:
1250 value is OracleDate? ((OracleDate) value).IsNull:
1251 value is OracleTimeStamp? ((OracleTimeStamp) value).IsNull:
1252 value is OracleTimeStampTZ? ((OracleTimeStampTZ) value).IsNull:
1253 value is OracleTimeStampLTZ? ((OracleTimeStampLTZ)value).IsNull:
1254 #if !MANAGED
1255 value is OracleXmlType? ((OracleXmlType) value).IsNull:
1256 #endif
1257 value is OracleBlob? ((OracleBlob) value).IsNull:
1258 value is OracleClob? ((OracleClob) value).IsNull:
1259 value is OracleBFile? ((OracleBFile) value).IsNull:
1260 value is OracleBinary? ((OracleBinary) value).IsNull:
1261 value is OracleIntervalDS? ((OracleIntervalDS) value).IsNull:
1262 value is OracleIntervalYM? ((OracleIntervalYM) value).IsNull:
1263 base.IsNull(value);
1264 }
1265 }
1266
1267 // TODO: implement via IDataReaderEx / DataReaderEx
1268 //
1269 public class OracleDataReaderMapper : DataReaderMapper
1270 {
1271 public OracleDataReaderMapper(MappingSchema mappingSchema, IDataReader dataReader)
1272 : base(mappingSchema, dataReader)
1273 {
1274 _dataReader = dataReader is OracleDataReaderEx?
1275 ((OracleDataReaderEx)dataReader).DataReader:
1276 (OracleDataReader)dataReader;
1277 }
1278
1279 private readonly OracleDataReader _dataReader;
1280
1281 public override Type GetFieldType(int index)
1282 {
1283 var fieldType = _dataReader.GetProviderSpecificFieldType(index);
1284
1285 if (fieldType != typeof(OracleBlob)
1286 #if !MANAGED
1287 && fieldType != typeof(OracleXmlType)
1288 #endif
1289 )
1290 fieldType = _dataReader.GetFieldType(index);
1291
1292 return fieldType;
1293 }
1294
1295 public override object GetValue(object o, int index)
1296 {
1297 var fieldType = _dataReader.GetProviderSpecificFieldType(index);
1298
1299 #if !MANAGED
1300 if (fieldType == typeof(OracleXmlType))
1301 {
1302 var xml = _dataReader.GetOracleXmlType(index);
1303 return MappingSchema.ConvertToXmlDocument(xml);
1304 }
1305 #endif
1306 if (fieldType == typeof(OracleBlob))
1307 {
1308 var blob = _dataReader.GetOracleBlob(index);
1309 return MappingSchema.ConvertToStream(blob);
1310 }
1311
1312 return _dataReader.IsDBNull(index)? null:
1313 _dataReader.GetValue(index);
1314 }
1315
1316 public override Boolean GetBoolean(object o, int index) { return MappingSchema.ConvertToBoolean(GetValue(o, index)); }
1317 public override Char GetChar (object o, int index) { return MappingSchema.ConvertToChar (GetValue(o, index)); }
1318 public override Guid GetGuid (object o, int index) { return MappingSchema.ConvertToGuid (GetValue(o, index)); }
1319
1320 [CLSCompliant(false)]
1321 public override SByte GetSByte (object o, int index) { return (SByte)_dataReader.GetDecimal(index); }
1322 [CLSCompliant(false)]
1323 public override UInt16 GetUInt16 (object o, int index) { return (UInt16)_dataReader.GetDecimal(index); }
1324 [CLSCompliant(false)]
1325 public override UInt32 GetUInt32 (object o, int index) { return (UInt32)_dataReader.GetDecimal(index); }
1326 [CLSCompliant(false)]
1327 public override UInt64 GetUInt64 (object o, int index) { return (UInt64)_dataReader.GetDecimal(index); }
1328
1329 public override Decimal GetDecimal(object o, int index) { return OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(index), 28).Value; }
1330
1331 public override Boolean? GetNullableBoolean(object o, int index) { return MappingSchema.ConvertToNullableBoolean(GetValue(o, index)); }
1332 public override Char? GetNullableChar (object o, int index) { return MappingSchema.ConvertToNullableChar (GetValue(o, index)); }
1333 public override Guid? GetNullableGuid (object o, int index) { return MappingSchema.ConvertToNullableGuid (GetValue(o, index)); }
1334
1335 [CLSCompliant(false)]
1336 public override SByte? GetNullableSByte (object o, int index) { return _dataReader.IsDBNull(index)? null: (SByte?)_dataReader.GetDecimal(index); }
1337 [CLSCompliant(false)]
1338 public override UInt16? GetNullableUInt16 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt16?)_dataReader.GetDecimal(index); }
1339 [CLSCompliant(false)]
1340 public override UInt32? GetNullableUInt32 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt32?)_dataReader.GetDecimal(index); }
1341 [CLSCompliant(false)]
1342 public override UInt64? GetNullableUInt64 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt64?)_dataReader.GetDecimal(index); }
1343
1344 public override Decimal? GetNullableDecimal(object o, int index) { return _dataReader.IsDBNull(index)? (decimal?)null: OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(index), 28).Value; }
1345 }
1346
1347 public class OracleScalarDataReaderMapper : ScalarDataReaderMapper
1348 {
1349 private readonly OracleDataReader _dataReader;
1350
1351 public OracleScalarDataReaderMapper(
1352 MappingSchema mappingSchema,
1353 IDataReader dataReader,
1354 NameOrIndexParameter nameOrIndex)
1355 : base(mappingSchema, dataReader, nameOrIndex)
1356 {
1357 _dataReader = dataReader is OracleDataReaderEx?
1358 ((OracleDataReaderEx)dataReader).DataReader:
1359 (OracleDataReader)dataReader;
1360
1361 _fieldType = _dataReader.GetProviderSpecificFieldType(Index);
1362
1363 if (_fieldType != typeof(OracleBlob)
1364 #if !MANAGED
1365 && _fieldType != typeof(OracleXmlType)
1366 #endif
1367 )
1368 _fieldType = _dataReader.GetFieldType(Index);
1369 }
1370
1371 private readonly Type _fieldType;
1372
1373 public override Type GetFieldType(int index)
1374 {
1375 return _fieldType;
1376 }
1377
1378 public override object GetValue(object o, int index)
1379 {
1380 #if !MANAGED
1381 if (_fieldType == typeof(OracleXmlType))
1382 {
1383 var xml = _dataReader.GetOracleXmlType(Index);
1384 return MappingSchema.ConvertToXmlDocument(xml);
1385 }
1386 #endif
1387 if (_fieldType == typeof(OracleBlob))
1388 {
1389 var blob = _dataReader.GetOracleBlob(Index);
1390 return MappingSchema.ConvertToStream(blob);
1391 }
1392
1393 return _dataReader.IsDBNull(index)? null:
1394 _dataReader.GetValue(Index);
1395 }
1396
1397 public override Boolean GetBoolean(object o, int index) { return MappingSchema.ConvertToBoolean(GetValue(o, Index)); }
1398 public override Char GetChar (object o, int index) { return MappingSchema.ConvertToChar (GetValue(o, Index)); }
1399 public override Guid GetGuid (object o, int index) { return MappingSchema.ConvertToGuid (GetValue(o, Index)); }
1400
1401 [CLSCompliant(false)]
1402 public override SByte GetSByte (object o, int index) { return (SByte)_dataReader.GetDecimal(Index); }
1403 [CLSCompliant(false)]
1404 public override UInt16 GetUInt16 (object o, int index) { return (UInt16)_dataReader.GetDecimal(Index); }
1405 [CLSCompliant(false)]
1406 public override UInt32 GetUInt32 (object o, int index) { return (UInt32)_dataReader.GetDecimal(Index); }
1407 [CLSCompliant(false)]
1408 public override UInt64 GetUInt64 (object o, int index) { return (UInt64)_dataReader.GetDecimal(Index); }
1409
1410 public override Decimal GetDecimal(object o, int index) { return OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(Index), 28).Value; }
1411
1412 public override Boolean? GetNullableBoolean(object o, int index) { return MappingSchema.ConvertToNullableBoolean(GetValue(o, Index)); }
1413 public override Char? GetNullableChar (object o, int index) { return MappingSchema.ConvertToNullableChar (GetValue(o, Index)); }
1414 public override Guid? GetNullableGuid (object o, int index) { return MappingSchema.ConvertToNullableGuid (GetValue(o, Index)); }
1415
1416 [CLSCompliant(false)]
1417 public override SByte? GetNullableSByte (object o, int index) { return _dataReader.IsDBNull(index)? null: (SByte?)_dataReader.GetDecimal(Index); }
1418 [CLSCompliant(false)]
1419 public override UInt16? GetNullableUInt16 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt16?)_dataReader.GetDecimal(Index); }
1420 [CLSCompliant(false)]
1421 public override UInt32? GetNullableUInt32 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt32?)_dataReader.GetDecimal(Index); }
1422 [CLSCompliant(false)]
1423 public override UInt64? GetNullableUInt64 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt64?)_dataReader.GetDecimal(Index); }
1424
1425 public override Decimal? GetNullableDecimal(object o, int index) { return _dataReader.IsDBNull(index)? (decimal?)null: OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(Index), 28).Value; }
1426 }
1427
1428 [Mixin(typeof(IDbDataParameter), "_oracleParameter")]
1429 [Mixin(typeof(IDataParameter), "_oracleParameter")]
1430 [Mixin(typeof(IDisposable), "_oracleParameter")]
1431 [Mixin(typeof(ICloneable), "_oracleParameter")]
1432 [CLSCompliant(false)]
1433 public abstract class OracleParameterWrap
1434 {
1435 protected OracleParameter _oracleParameter;
1436 public OracleParameter OracleParameter
1437 {
1438 get { return _oracleParameter; }
1439 }
1440
1441 public static IDbDataParameter CreateInstance(OracleParameter oraParameter)
1442 {
1443 var wrap = TypeAccessor<OracleParameterWrap>.CreateInstanceEx();
1444
1445 wrap._oracleParameter = oraParameter;
1446
1447 return (IDbDataParameter)wrap;
1448 }
1449
1450 public override string ToString()
1451 {
1452 return _oracleParameter.ToString();
1453 }
1454
1455 ///<summary>
1456 ///Gets or sets the value of the parameter.
1457 ///</summary>
1458 ///<returns>
1459 ///An <see cref="T:System.Object"/> that is the value of the parameter.
1460 ///The default value is null.
1461 ///</returns>
1462 protected object Value
1463 {
1464 #if CONVERTORACLETYPES
1465 [MixinOverride]
1466 get
1467 {
1468 object value = _oracleParameter.Value;
1469 if (value is OracleBinary)
1470 {
1471 OracleBinary oracleValue = (OracleBinary)value;
1472 return oracleValue.IsNull? null: oracleValue.Value;
1473 }
1474 if (value is OracleDate)
1475 {
1476 OracleDate oracleValue = (OracleDate)value;
1477 if (oracleValue.IsNull)
1478 return null;
1479 return oracleValue.Value;
1480 }
1481 if (value is OracleDecimal)
1482 {
1483 OracleDecimal oracleValue = (OracleDecimal)value;
1484 if (oracleValue.IsNull)
1485 return null;
1486 return oracleValue.Value;
1487 }
1488 if (value is OracleIntervalDS)
1489 {
1490 OracleIntervalDS oracleValue = (OracleIntervalDS)value;
1491 if (oracleValue.IsNull)
1492 return null;
1493 return oracleValue.Value;
1494 }
1495 if (value is OracleIntervalYM)
1496 {
1497 OracleIntervalYM oracleValue = (OracleIntervalYM)value;
1498 if (oracleValue.IsNull)
1499 return null;
1500 return oracleValue.Value;
1501 }
1502 if (value is OracleString)
1503 {
1504 OracleString oracleValue = (OracleString)value;
1505 return oracleValue.IsNull? null: oracleValue.Value;
1506 }
1507 if (value is OracleTimeStamp)
1508 {
1509 OracleTimeStamp oracleValue = (OracleTimeStamp)value;
1510 if (oracleValue.IsNull)
1511 return null;
1512 return oracleValue.Value;
1513 }
1514 if (value is OracleTimeStampLTZ)
1515 {
1516 OracleTimeStampLTZ oracleValue = (OracleTimeStampLTZ)value;
1517 if (oracleValue.IsNull)
1518 return null;
1519 return oracleValue.Value;
1520 }
1521 if (value is OracleTimeStampTZ)
1522 {
1523 OracleTimeStampTZ oracleValue = (OracleTimeStampTZ)value;
1524 if (oracleValue.IsNull)
1525 return null;
1526 return oracleValue.Value;
1527 }
1528 if (value is OracleXmlType)
1529 {
1530 OracleXmlType oracleValue = (OracleXmlType)value;
1531 return oracleValue.IsNull? null: oracleValue.Value;
1532 }
1533
1534 return value;
1535 }
1536 #endif
1537 [MixinOverride]
1538 set
1539 {
1540 if (null != value)
1541 {
1542 if (value is Guid)
1543 {
1544 // Fix Oracle.Net bug #6: guid type is not handled
1545 //
1546 value = ((Guid)value).ToByteArray();
1547 }
1548 else if (value is Array && !(value is byte[] || value is char[]))
1549 {
1550 _oracleParameter.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
1551 }
1552 else if (value is IConvertible)
1553 {
1554 var convertible = (IConvertible)value;
1555 var typeCode = convertible.GetTypeCode();
1556
1557 switch (typeCode)
1558 {
1559 case TypeCode.Boolean:
1560 // Fix Oracle.Net bug #7: bool type is handled wrong
1561 //
1562 value = convertible.ToByte(null);
1563 break;
1564
1565 case TypeCode.SByte:
1566 case TypeCode.UInt16:
1567 case TypeCode.UInt32:
1568 case TypeCode.UInt64:
1569 // Fix Oracle.Net bug #8: some integer types are handled wrong
1570 //
1571 value = convertible.ToDecimal(null);
1572 break;
1573
1574 // Fix Oracle.Net bug #10: zero-length string can not be converted to
1575 // ORAXML type, but null value can be.
1576 //
1577 case TypeCode.String:
1578 if (((string)value).Length == 0)
1579 value = null;
1580 break;
1581
1582 default:
1583 // Fix Oracle.Net bug #5: Enum type is not handled
1584 //
1585 if (value is Enum)
1586 {
1587 // Convert a Enum value to it's underlying type.
1588 //
1589 value = System.Convert.ChangeType(value, typeCode);
1590 }
1591 break;
1592 }
1593 }
1594 }
1595
1596 _oracleParameter.Value = value;
1597 }
1598 }
1599 }
1600
1601 #endregion
1602
1603 #region InsertBatch
1604
1605 public override int InsertBatch<T>(
1606 DbManager db,
1607 string insertText,
1608 IEnumerable<T> collection,
1609 MemberMapper[] members,
1610 int maxBatchSize,
1611 DbManager.ParameterProvider<T> getParameters)
1612 {
1613 var sb = new StringBuilder();
1614 var sp = new OracleSqlProvider();
1615 var pn = 0;
1616 var n = 0;
1617 var cnt = 0;
1618 var str = "\t" + insertText
1619 .Substring(0, insertText.IndexOf(") VALUES ("))
1620 .Substring(7)
1621 .Replace("\r", "")
1622 .Replace("\n", "")
1623 .Replace("\t", " ")
1624 .Replace("( ", "(")
1625 //.Replace(" ", " ")
1626 + ") VALUES (";
1627
1628 var parameters = new List<IDbDataParameter>();
1629
1630 foreach (var item in collection)
1631 {
1632 if (sb.Length == 0)
1633 sb.AppendLine("INSERT ALL");
1634
1635 sb.Append(str);
1636
1637 foreach (var member in members)
1638 {
1639 var value = member.GetValue(item);
1640
1641 if (value != null && value.GetType().IsEnum)
1642 value = MappingSchema.MapEnumToValue(value, true);
1643
1644 if (value is Nullable<DateTime>)
1645 value = ((DateTime?)value).Value;
1646
1647 if (value is DateTime)
1648 {
1649 var dt = (DateTime)value;
1650 sb.Append(string.Format("to_timestamp('{0:dd.MM.yyyy HH:mm:ss.ffffff}', 'DD.MM.YYYY HH24:MI:SS.FF6')", dt));
1651 }
1652 else if (value is string && ((string)value).Length >= 2000)
1653 {
1654 var par = db.Parameter("p" + ++pn, value);
1655 parameters.Add(par);
1656 sb.Append(":" + par.ParameterName);
1657 }
1658 else
1659 sp.BuildValue(sb, value);
1660
1661 sb.Append(", ");
1662 }
1663
1664 sb.Length -= 2;
1665 sb.AppendLine(")");
1666
1667 n++;
1668
1669 if (n >= maxBatchSize)
1670 {
1671 sb.AppendLine("SELECT * FROM dual");
1672
1673 var sql = sb.ToString();
1674
1675 if (DbManager.TraceSwitch.TraceInfo)
1676 DbManager.WriteTraceLine("\n" + sql.Replace("\r", ""), DbManager.TraceSwitch.DisplayName);
1677
1678 cnt += db
1679 .SetCommand(sql, parameters.Count > 0 ? parameters.ToArray() : null)
1680 .ExecuteNonQuery();
1681
1682 parameters.Clear();
1683 pn = 0;
1684 n = 0;
1685 sb.Length = 0;
1686 }
1687 }
1688
1689 if (n > 0)
1690 {
1691 sb.AppendLine("SELECT * FROM dual");
1692
1693 var sql = sb.ToString();
1694
1695 if (DbManager.TraceSwitch.TraceInfo)
1696 DbManager.WriteTraceLine("\n" + sql.Replace("\r", ""), DbManager.TraceSwitch.DisplayName);
1697
1698 cnt += db
1699 .SetCommand(sql, parameters.Count > 0 ? parameters.ToArray() : null)
1700 .ExecuteNonQuery();
1701 }
1702
1703 return cnt;
1704 }
1705
1706 #endregion
1707 }
1708 }