Mercurial > pub > bltoolkit
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 } |