// Odp.Net Data Provider.
// http://www.oracle.com/technology/tech/windows/odpnet/index.html
//
using System;
using System.Collections;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Xml;
using BLToolkit.Aspects;
using BLToolkit.Common;
using BLToolkit.Mapping;
using BLToolkit.Reflection;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;
namespace BLToolkit.Data.DataProvider
{
using Sql.SqlProvider;
/// <summary>
/// Implements access to the Data Provider for Oracle.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
public class OdpDataProvider : DataProviderBase
{
public OdpDataProvider()
{
MappingSchema = new OdpMappingSchema();
}
static OdpDataProvider()
{
// Fix Oracle.Net bug #1: Array types are not handled.
//
Type OraDb_DbTypeTableType = typeof(OracleParameter).Assembly
.GetType("Oracle.DataAccess.Client.OraDb_DbTypeTable");
if (null != OraDb_DbTypeTableType)
{
Hashtable typeTable = (Hashtable)OraDb_DbTypeTableType.InvokeMember(
"s_table", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.GetField,
null, null, Type.EmptyTypes);
if (null != typeTable)
{
typeTable[typeof(DateTime[])] = OracleDbType.TimeStamp;
typeTable[typeof(Int16[])] = OracleDbType.Int16;
typeTable[typeof(Int32[])] = OracleDbType.Int32;
typeTable[typeof(Int64[])] = OracleDbType.Int64;
typeTable[typeof(Single[])] = OracleDbType.Single;
typeTable[typeof(Double[])] = OracleDbType.Double;
typeTable[typeof(Decimal[])] = OracleDbType.Decimal;
typeTable[typeof(TimeSpan[])] = OracleDbType.IntervalDS;
typeTable[typeof(String[])] = OracleDbType.Varchar2;
typeTable[typeof(OracleBFile[])] = OracleDbType.BFile;
typeTable[typeof(OracleBinary[])] = OracleDbType.Raw;
typeTable[typeof(OracleBlob[])] = OracleDbType.Blob;
typeTable[typeof(OracleClob[])] = OracleDbType.Clob;
typeTable[typeof(OracleDate[])] = OracleDbType.Date;
typeTable[typeof(OracleDecimal[])] = OracleDbType.Decimal;
typeTable[typeof(OracleIntervalDS[])] = OracleDbType.IntervalDS;
typeTable[typeof(OracleIntervalYM[])] = OracleDbType.IntervalYM;
typeTable[typeof(OracleRefCursor[])] = OracleDbType.RefCursor;
typeTable[typeof(OracleString[])] = OracleDbType.Varchar2;
typeTable[typeof(OracleTimeStamp[])] = OracleDbType.TimeStamp;
typeTable[typeof(OracleTimeStampLTZ[])]= OracleDbType.TimeStampLTZ;
typeTable[typeof(OracleTimeStampTZ[])] = OracleDbType.TimeStampTZ;
typeTable[typeof(OracleXmlType[])] = OracleDbType.XmlType;
typeTable[typeof(Boolean)] = OracleDbType.Byte;
typeTable[typeof(Guid)] = OracleDbType.Raw;
typeTable[typeof(SByte)] = OracleDbType.Decimal;
typeTable[typeof(UInt16)] = OracleDbType.Decimal;
typeTable[typeof(UInt32)] = OracleDbType.Decimal;
typeTable[typeof(UInt64)] = OracleDbType.Decimal;
typeTable[typeof(Boolean[])] = OracleDbType.Byte;
typeTable[typeof(Guid[])] = OracleDbType.Raw;
typeTable[typeof(SByte[])] = OracleDbType.Decimal;
typeTable[typeof(UInt16[])] = OracleDbType.Decimal;
typeTable[typeof(UInt32[])] = OracleDbType.Decimal;
typeTable[typeof(UInt64[])] = OracleDbType.Decimal;
typeTable[typeof(Boolean?)] = OracleDbType.Byte;
typeTable[typeof(Guid?)] = OracleDbType.Raw;
typeTable[typeof(SByte?)] = OracleDbType.Decimal;
typeTable[typeof(UInt16?)] = OracleDbType.Decimal;
typeTable[typeof(UInt32?)] = OracleDbType.Decimal;
typeTable[typeof(UInt64?)] = OracleDbType.Decimal;
typeTable[typeof(DateTime?[])] = OracleDbType.TimeStamp;
typeTable[typeof(Int16?[])] = OracleDbType.Int16;
typeTable[typeof(Int32?[])] = OracleDbType.Int32;
typeTable[typeof(Int64?[])] = OracleDbType.Int64;
typeTable[typeof(Single?[])] = OracleDbType.Single;
typeTable[typeof(Double?[])] = OracleDbType.Double;
typeTable[typeof(Decimal?[])] = OracleDbType.Decimal;
typeTable[typeof(TimeSpan?[])] = OracleDbType.IntervalDS;
typeTable[typeof(Boolean?[])] = OracleDbType.Byte;
typeTable[typeof(Guid?[])] = OracleDbType.Raw;
typeTable[typeof(SByte?[])] = OracleDbType.Decimal;
typeTable[typeof(UInt16?[])] = OracleDbType.Decimal;
typeTable[typeof(UInt32?[])] = OracleDbType.Decimal;
typeTable[typeof(UInt64?[])] = OracleDbType.Decimal;
typeTable[typeof(XmlReader)] = OracleDbType.XmlType;
typeTable[typeof(XmlDocument)] = OracleDbType.XmlType;
typeTable[typeof(MemoryStream)] = OracleDbType.Blob;
typeTable[typeof(XmlReader[])] = OracleDbType.XmlType;
typeTable[typeof(XmlDocument[])] = OracleDbType.XmlType;
typeTable[typeof(MemoryStream[])] = OracleDbType.Blob;
}
}
}
/// <summary>
/// Creates the database connection object.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
/// <returns>The database connection object.</returns>
public override IDbConnection CreateConnectionObject()
{
return new OracleConnection();
}
public override IDbCommand CreateCommandObject(IDbConnection connection)
{
OracleConnection oraConnection = connection as OracleConnection;
if (null != oraConnection)
{
OracleCommand oraCommand = oraConnection.CreateCommand();
// Fix Oracle.Net bug #2: Empty arrays can not be sent to the server.
//
oraCommand.BindByName = true;
return oraCommand;
}
return base.CreateCommandObject(connection);
}
public override IDbDataParameter CloneParameter(IDbDataParameter parameter)
{
OracleParameter oraParameter = (parameter is OracleParameterWrap)?
(parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
if (null != oraParameter)
{
OracleParameter oraParameterClone = (OracleParameter)oraParameter.Clone();
// Fix Oracle.Net bug #3: CollectionType property is not cloned.
//
oraParameterClone.CollectionType = oraParameter.CollectionType;
// Fix Oracle.Net bug #8423178
// See http://forums.oracle.com/forums/thread.jspa?threadID=975902&tstart=0
//
if (oraParameterClone.OracleDbType == OracleDbType.RefCursor)
{
// Set OracleDbType to itself to reset m_bSetDbType and m_bOracleDbTypeExSet
//
oraParameterClone.OracleDbType = OracleDbType.RefCursor;
}
return OracleParameterWrap.CreateInstance(oraParameterClone);
}
return base.CloneParameter(parameter);
}
public override void SetUserDefinedType(IDbDataParameter parameter, string typeName)
{
OracleParameter oraParameter = (parameter is OracleParameterWrap) ?
(parameter as OracleParameterWrap).OracleParameter : parameter as OracleParameter;
if (oraParameter == null)
throw new ArgumentException("OracleParameter expected.", "parameter");
oraParameter.UdtTypeName = typeName;
}
/// <summary>
/// Creates the data adapter object.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
/// <returns>A data adapter object.</returns>
public override DbDataAdapter CreateDataAdapterObject()
{
return new OracleDataAdapter();
}
/// <summary>
/// Populates the specified IDbCommand object's Parameters collection with
/// parameter information for the stored procedure specified in the IDbCommand.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
/// <param name="command">The IDbCommand referencing the stored procedure for which the parameter
/// information is to be derived. The derived parameters will be populated into
/// the Parameters of this command.</param>
public override bool DeriveParameters(IDbCommand command)
{
OracleCommand oraCommand = command as OracleCommand;
if (null != oraCommand)
{
try
{
OracleCommandBuilder.DeriveParameters(oraCommand);
}
catch (Exception ex)
{
// Make Oracle less laconic.
//
throw new DataException(string.Format("{0}\nCommandText: {1}", ex.Message, oraCommand.CommandText), ex);
}
return true;
}
return false;
}
public override object Convert(object value, ConvertType convertType)
{
switch (convertType)
{
case ConvertType.NameToQueryParameter:
return ":" + value;
case ConvertType.NameToCommandParameter:
case ConvertType.NameToSprocParameter:
return ParameterPrefix == null? value: ParameterPrefix + value;
case ConvertType.SprocParameterToName:
string name = (string)value;
if (name.Length > 0)
{
if (name[0] == ':')
return name.Substring(1);
if (ParameterPrefix != null &&
name.ToUpper(CultureInfo.InvariantCulture).StartsWith(ParameterPrefix))
{
return name.Substring(ParameterPrefix.Length);
}
}
break;
case ConvertType.ExceptionToErrorNumber:
if (value is OracleException)
return ((OracleException)value).Number;
break;
}
return value;
}
public override void PrepareCommand(ref CommandType commandType, ref string commandText, ref IDbDataParameter[] commandParameters)
{
base.PrepareCommand(ref commandType, ref commandText, ref commandParameters);
if (commandType == CommandType.Text)
{
// Fix Oracle bug #11 '\r' is not a valid character!
//
commandText = commandText.Replace('\r', ' ');
}
}
public override void AttachParameter(IDbCommand command, IDbDataParameter parameter)
{
OracleParameter oraParameter = (parameter is OracleParameterWrap)?
(parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
if (null != oraParameter)
{
if (oraParameter.CollectionType == OracleCollectionType.PLSQLAssociativeArray)
{
if (oraParameter.Direction == ParameterDirection.Input
|| oraParameter.Direction == ParameterDirection.InputOutput)
{
Array ar = oraParameter.Value as Array;
if (null != ar && !(ar is byte[] || ar is char[]))
{
oraParameter.Size = ar.Length;
if (oraParameter.DbType == DbType.String
&& oraParameter.Direction == ParameterDirection.InputOutput)
{
int[] arrayBindSize = new int[oraParameter.Size];
for (int i = 0; i < oraParameter.Size; ++i)
{
arrayBindSize[i] = 1024;
}
oraParameter.ArrayBindSize = arrayBindSize;
}
}
if (oraParameter.Size == 0)
{
// Skip this parameter.
// Fix Oracle.Net bug #2: Empty arrays can not be sent to the server.
//
return;
}
if (oraParameter.Value is Stream[])
{
Stream[] streams = (Stream[]) oraParameter.Value;
for (int i = 0; i < oraParameter.Size; ++i)
{
if (streams[i] is OracleBFile || streams[i] is OracleBlob ||
streams[i] is OracleClob || streams[i] is OracleXmlStream)
{
// Known Oracle type.
//
continue;
}
streams[i] = CopyStream(streams[i], (OracleCommand)command);
}
}
else if (oraParameter.Value is XmlDocument[])
{
XmlDocument[] xmlDocuments = (XmlDocument[]) oraParameter.Value;
object[] values = new object[oraParameter.Size];
switch (oraParameter.OracleDbType)
{
case OracleDbType.XmlType:
for (int i = 0; i < oraParameter.Size; ++i)
{
values[i] = xmlDocuments[i].DocumentElement == null?
(object) DBNull.Value:
new OracleXmlType((OracleConnection)command.Connection, xmlDocuments[i]);
}
oraParameter.Value = values;
break;
// Fix Oracle.Net bug #9: XmlDocument.ToString() returns System.Xml.XmlDocument,
// so m_value.ToString() is not enought.
//
case OracleDbType.Clob:
case OracleDbType.NClob:
case OracleDbType.Varchar2:
case OracleDbType.NVarchar2:
case OracleDbType.Char:
case OracleDbType.NChar:
for (int i = 0; i < oraParameter.Size; ++i)
{
values[i] = xmlDocuments[i].DocumentElement == null?
(object) DBNull.Value:
xmlDocuments[i].InnerXml;
}
oraParameter.Value = values;
break;
// Or convert to bytes if need.
//
case OracleDbType.Blob:
case OracleDbType.BFile:
case OracleDbType.Raw:
case OracleDbType.Long:
case OracleDbType.LongRaw:
for (int i = 0; i < oraParameter.Size; ++i)
{
if (xmlDocuments[i].DocumentElement == null)
values[i] = DBNull.Value;
else
using (MemoryStream s = new MemoryStream())
{
xmlDocuments[i].Save(s);
values[i] = s.GetBuffer();
}
}
oraParameter.Value = values;
break;
}
}
}
else if (oraParameter.Direction == ParameterDirection.Output)
{
// Fix Oracle.Net bug #4: ArrayBindSize must be explicitly specified.
//
if (oraParameter.DbType == DbType.String)
{
oraParameter.Size = 1024;
int[] arrayBindSize = new int[oraParameter.Size];
for (int i = 0; i < oraParameter.Size; ++i)
{
arrayBindSize[i] = 1024;
}
oraParameter.ArrayBindSize = arrayBindSize;
}
else
{
oraParameter.Size = 32767;
}
}
}
else if (oraParameter.Value is Stream)
{
Stream stream = (Stream) oraParameter.Value;
if (!(stream is OracleBFile) && !(stream is OracleBlob) &&
!(stream is OracleClob) && !(stream is OracleXmlStream))
{
oraParameter.Value = CopyStream(stream, (OracleCommand)command);
}
}
else if (oraParameter.Value is Byte[])
{
Byte[] bytes = (Byte[]) oraParameter.Value;
if (bytes.Length > 32000)
{
oraParameter.Value = CopyStream(bytes, (OracleCommand)command);
}
}
else if (oraParameter.Value is XmlDocument)
{
XmlDocument xmlDocument = (XmlDocument)oraParameter.Value;
if (xmlDocument.DocumentElement == null)
oraParameter.Value = DBNull.Value;
else
{
switch (oraParameter.OracleDbType)
{
case OracleDbType.XmlType:
oraParameter.Value = new OracleXmlType((OracleConnection)command.Connection, xmlDocument);
break;
// Fix Oracle.Net bug #9: XmlDocument.ToString() returns System.Xml.XmlDocument,
// so m_value.ToString() is not enought.
//
case OracleDbType.Clob:
case OracleDbType.NClob:
case OracleDbType.Varchar2:
case OracleDbType.NVarchar2:
case OracleDbType.Char:
case OracleDbType.NChar:
using (TextWriter w = new StringWriter())
{
xmlDocument.Save(w);
oraParameter.Value = w.ToString();
}
break;
// Or convert to bytes if need.
//
case OracleDbType.Blob:
case OracleDbType.BFile:
case OracleDbType.Raw:
case OracleDbType.Long:
case OracleDbType.LongRaw:
using (MemoryStream s = new MemoryStream())
{
xmlDocument.Save(s);
oraParameter.Value = s.GetBuffer();
}
break;
}
}
}
parameter = oraParameter;
}
base.AttachParameter(command, parameter);
}
private static Stream CopyStream(Stream stream, OracleCommand cmd)
{
return CopyStream(BLToolkit.Common.Convert.ToByteArray(stream), cmd);
}
private static Stream CopyStream(Byte[] bytes, OracleCommand cmd)
{
OracleBlob ret = new OracleBlob(cmd.Connection);
ret.Write(bytes, 0, bytes.Length);
return ret;
}
public override bool IsValueParameter(IDbDataParameter parameter)
{
OracleParameter oraParameter = (parameter is OracleParameterWrap)?
(parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter;
if (null != oraParameter)
{
if (oraParameter.OracleDbType == OracleDbType.RefCursor
&& oraParameter.Direction == ParameterDirection.Output)
{
// Ignore out ref cursors, while out parameters of other types are o.k.
return false;
}
}
return base.IsValueParameter(parameter);
}
public override IDbDataParameter CreateParameterObject(IDbCommand command)
{
IDbDataParameter parameter = base.CreateParameterObject(command);
if (parameter is OracleParameter)
parameter = OracleParameterWrap.CreateInstance(parameter as OracleParameter);
return parameter;
}
public override IDbDataParameter GetParameter(IDbCommand command, NameOrIndexParameter nameOrIndex)
{
IDbDataParameter parameter = base.GetParameter(command, nameOrIndex);
if (parameter is OracleParameter)
parameter = OracleParameterWrap.CreateInstance(parameter as OracleParameter);
return parameter;
}
/// <summary>
/// Returns connection type.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataManager Method</seealso>
/// <value>An instance of the <see cref="Type"/> class.</value>
public override Type ConnectionType
{
get { return typeof(OracleConnection); }
}
public const string NameString = DataProvider.ProviderName.Oracle;
/// <summary>
/// Returns the data provider name.
/// </summary>
/// <remarks>
/// See the <see cref="DbManager.AddDataProvider(DataProviderBase)"/> method to find an example.
/// </remarks>
/// <seealso cref="DbManager.AddDataProvider(DataProviderBase)">AddDataProvider Method</seealso>
/// <value>Data provider name.</value>
public override string Name
{
get { return NameString; }
}
public override int MaxBatchSize
{
get { return 0; }
}
public override ISqlProvider CreateSqlProvider()
{
return new OracleSqlProvider(this);
}
#if FW3
public override IDataReader GetDataReader(MappingSchema schema, IDataReader dataReader)
{
return dataReader is OracleDataReader ?
new OracleDataReaderEx((OracleDataReader)dataReader) :
base.GetDataReader(schema, dataReader);
}
class OracleDataReaderEx: DataReaderEx<OracleDataReader>
{
public OracleDataReaderEx(OracleDataReader rd)
: base(rd)
{
}
public override DateTimeOffset GetDateTimeOffset(int i)
{
OracleTimeStampTZ ts = DataReader.GetOracleTimeStampTZ(i);
return new DateTimeOffset(ts.Value, ts.GetTimeZoneOffset());
}
}
#endif
private string _parameterPrefix = "P";
public string ParameterPrefix
{
get { return _parameterPrefix; }
set
{
_parameterPrefix = string.IsNullOrEmpty(value)? null:
value.ToUpper(CultureInfo.InvariantCulture);
}
}
/// <summary>
/// One time initialization from a configuration file.
/// </summary>
/// <param name="attributes">Provider specific attributes.</param>
public override void Configure(System.Collections.Specialized.NameValueCollection attributes)
{
string val = attributes["ParameterPrefix"];
if (val != null)
ParameterPrefix = val;
base.Configure(attributes);
}
#region Inner types
public class OdpMappingSchema : MappingSchema
{
public override DataReaderMapper CreateDataReaderMapper(IDataReader dataReader)
{
return new OracleDataReaderMapper(this, dataReader);
}
public override DataReaderMapper CreateDataReaderMapper(
IDataReader dataReader,
NameOrIndexParameter nip)
{
return new OracleScalarDataReaderMapper(this, dataReader, nip);
}
#region Convert
#region Primitive Types
[CLSCompliant(false)]
public override SByte ConvertToSByte(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultSByteNullValue: (SByte)oraDecimal.Value;
}
return base.ConvertToSByte(value);
}
public override Int16 ConvertToInt16(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultInt16NullValue: oraDecimal.ToInt16();
}
return base.ConvertToInt16(value);
}
public override Int32 ConvertToInt32(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultInt32NullValue: oraDecimal.ToInt32();
}
return base.ConvertToInt32(value);
}
public override Int64 ConvertToInt64(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultInt64NullValue: oraDecimal.ToInt64();
}
return base.ConvertToInt64(value);
}
public override Byte ConvertToByte(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultByteNullValue: oraDecimal.ToByte();
}
return base.ConvertToByte(value);
}
[CLSCompliant(false)]
public override UInt16 ConvertToUInt16(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultUInt16NullValue: (UInt16)oraDecimal.Value;
}
return base.ConvertToUInt16(value);
}
[CLSCompliant(false)]
public override UInt32 ConvertToUInt32(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultUInt32NullValue: (UInt32)oraDecimal.Value;
}
return base.ConvertToUInt32(value);
}
[CLSCompliant(false)]
public override UInt64 ConvertToUInt64(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultUInt64NullValue: (UInt64)oraDecimal.Value;
}
return base.ConvertToUInt64(value);
}
public override Single ConvertToSingle(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultSingleNullValue: oraDecimal.ToSingle();
}
return base.ConvertToSingle(value);
}
public override Double ConvertToDouble(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultDoubleNullValue: oraDecimal.ToDouble();
}
return base.ConvertToDouble(value);
}
public override Boolean ConvertToBoolean(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultBooleanNullValue: (oraDecimal.Value != 0);
}
return base.ConvertToBoolean(value);
}
public override DateTime ConvertToDateTime(object value)
{
if (value is OracleDate)
{
OracleDate oraDate = (OracleDate)value;
return oraDate.IsNull? DefaultDateTimeNullValue: oraDate.Value;
}
return base.ConvertToDateTime(value);
}
public override Decimal ConvertToDecimal(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? DefaultDecimalNullValue: oraDecimal.Value;
}
return base.ConvertToDecimal(value);
}
public override Guid ConvertToGuid(object value)
{
if (value is OracleString)
{
OracleString oraString = (OracleString)value;
return oraString.IsNull? DefaultGuidNullValue: new Guid(oraString.Value);
}
if (value is OracleBlob)
{
OracleBlob oraBlob = (OracleBlob)value;
return oraBlob.IsNull? DefaultGuidNullValue: new Guid(oraBlob.Value);
}
return base.ConvertToGuid(value);
}
public override String ConvertToString(object value)
{
if (value is OracleString)
{
OracleString oraString = (OracleString)value;
return oraString.IsNull? DefaultStringNullValue: oraString.Value;
}
if (value is OracleXmlType)
{
OracleXmlType oraXmlType = (OracleXmlType)value;
return oraXmlType.IsNull ? DefaultStringNullValue : oraXmlType.Value;
}
if (value is OracleClob)
{
OracleClob oraClob = (OracleClob)value;
return oraClob.IsNull? DefaultStringNullValue: oraClob.Value;
}
return base.ConvertToString(value);
}
public override Stream ConvertToStream(object value)
{
if (value is OracleXmlType)
{
OracleXmlType oraXml = (OracleXmlType)value;
return oraXml.IsNull? DefaultStreamNullValue: oraXml.GetStream();
}
return base.ConvertToStream(value);
}
public override XmlReader ConvertToXmlReader(object value)
{
if (value is OracleXmlType)
{
OracleXmlType oraXml = (OracleXmlType)value;
return oraXml.IsNull? DefaultXmlReaderNullValue: oraXml.GetXmlReader();
}
return base.ConvertToXmlReader(value);
}
public override XmlDocument ConvertToXmlDocument(object value)
{
if (value is OracleXmlType)
{
OracleXmlType oraXml = (OracleXmlType)value;
return oraXml.IsNull? DefaultXmlDocumentNullValue: oraXml.GetXmlDocument();
}
return base.ConvertToXmlDocument(value);
}
public override Byte[] ConvertToByteArray(object value)
{
if (value is OracleBlob)
{
OracleBlob oraBlob = (OracleBlob)value;
return oraBlob.IsNull? null: oraBlob.Value;
}
if (value is OracleBinary)
{
OracleBinary oraBinary = (OracleBinary)value;
return oraBinary.IsNull? null: oraBinary.Value;
}
if (value is OracleBFile)
{
OracleBFile oraBFile = (OracleBFile)value;
return oraBFile.IsNull? null: oraBFile.Value;
}
return base.ConvertToByteArray(value);
}
public override Char[] ConvertToCharArray(object value)
{
if (value is OracleString)
{
OracleString oraString = (OracleString)value;
return oraString.IsNull? null: oraString.Value.ToCharArray();
}
if (value is OracleClob)
{
OracleClob oraClob = (OracleClob)value;
return oraClob.IsNull? null: oraClob.Value.ToCharArray();
}
return base.ConvertToCharArray(value);
}
#endregion
#region Nullable Types
[CLSCompliant(false)]
public override SByte? ConvertToNullableSByte(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (SByte?)oraDecimal.Value;
}
return base.ConvertToNullableSByte(value);
}
public override Int16? ConvertToNullableInt16(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Int16?)oraDecimal.ToInt16();
}
return base.ConvertToNullableInt16(value);
}
public override Int32? ConvertToNullableInt32(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Int32?)oraDecimal.ToInt32();
}
return base.ConvertToNullableInt32(value);
}
public override Int64? ConvertToNullableInt64(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Int64?)oraDecimal.ToInt64();
}
return base.ConvertToNullableInt64(value);
}
public override Byte? ConvertToNullableByte(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Byte?)oraDecimal.ToByte();
}
return base.ConvertToNullableByte(value);
}
[CLSCompliant(false)]
public override UInt16? ConvertToNullableUInt16(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (UInt16?)oraDecimal.Value;
}
return base.ConvertToNullableUInt16(value);
}
[CLSCompliant(false)]
public override UInt32? ConvertToNullableUInt32(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (UInt32?)oraDecimal.Value;
}
return base.ConvertToNullableUInt32(value);
}
[CLSCompliant(false)]
public override UInt64? ConvertToNullableUInt64(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (UInt64?)oraDecimal.Value;
}
return base.ConvertToNullableUInt64(value);
}
public override Single? ConvertToNullableSingle(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Single?)oraDecimal.ToSingle();
}
return base.ConvertToNullableSingle(value);
}
public override Double? ConvertToNullableDouble(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Double?)oraDecimal.ToDouble();
}
return base.ConvertToNullableDouble(value);
}
public override Boolean? ConvertToNullableBoolean(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Boolean?)(oraDecimal.Value != 0);
}
return base.ConvertToNullableBoolean(value);
}
public override DateTime? ConvertToNullableDateTime(object value)
{
if (value is OracleDate)
{
OracleDate oraDate = (OracleDate)value;
return oraDate.IsNull? null: (DateTime?)oraDate.Value;
}
return base.ConvertToNullableDateTime(value);
}
public override Decimal? ConvertToNullableDecimal(object value)
{
if (value is OracleDecimal)
{
OracleDecimal oraDecimal = (OracleDecimal)value;
return oraDecimal.IsNull? null: (Decimal?)oraDecimal.Value;
}
return base.ConvertToNullableDecimal(value);
}
public override Guid? ConvertToNullableGuid(object value)
{
if (value is OracleString)
{
OracleString oraString = (OracleString)value;
return oraString.IsNull? null: (Guid?)new Guid(oraString.Value);
}
if (value is OracleBlob)
{
OracleBlob oraBlob = (OracleBlob)value;
return oraBlob.IsNull? null: (Guid?)new Guid(oraBlob.Value);
}
return base.ConvertToNullableGuid(value);
}
#endregion
#endregion
public override object MapValueToEnum(object value, Type type)
{
if (value is OracleString)
{
OracleString oracleValue = (OracleString)value;
value = oracleValue.IsNull? null: oracleValue.Value;
}
else if (value is OracleDecimal)
{
OracleDecimal oracleValue = (OracleDecimal)value;
if (oracleValue.IsNull)
value = null;
else
value = oracleValue.Value;
}
return base.MapValueToEnum(value, type);
}
public override object ConvertChangeType(object value, Type conversionType)
{
// Handle OracleDecimal with IsNull == true case
//
return base.ConvertChangeType(IsNull(value)? null: value, conversionType);
}
public override bool IsNull(object value)
{
// ODP 10 does not expose this interface to public.
//
// return value is INullable && ((INullable)value).IsNull;
return
value is OracleDecimal? ((OracleDecimal) value).IsNull:
value is OracleString? ((OracleString) value).IsNull:
value is OracleDate? ((OracleDate) value).IsNull:
value is OracleTimeStamp? ((OracleTimeStamp) value).IsNull:
value is OracleTimeStampTZ? ((OracleTimeStampTZ) value).IsNull:
value is OracleTimeStampLTZ? ((OracleTimeStampLTZ)value).IsNull:
value is OracleXmlType? ((OracleXmlType) value).IsNull:
value is OracleBlob? ((OracleBlob) value).IsNull:
value is OracleClob? ((OracleClob) value).IsNull:
value is OracleBFile? ((OracleBFile) value).IsNull:
value is OracleBinary? ((OracleBinary) value).IsNull:
value is OracleIntervalDS? ((OracleIntervalDS) value).IsNull:
value is OracleIntervalYM? ((OracleIntervalYM) value).IsNull:
base.IsNull(value);
}
}
// TODO: implement via IDataReaderEx / DataReaderEx
//
public class OracleDataReaderMapper : DataReaderMapper
{
public OracleDataReaderMapper(MappingSchema mappingSchema, IDataReader dataReader)
: base(mappingSchema, dataReader)
{
#if FW3
_dataReader = dataReader is OracleDataReaderEx?
((OracleDataReaderEx)dataReader).DataReader:
(OracleDataReader)dataReader;
#else
_dataReader = (OracleDataReader)dataReader;
#endif
}
private readonly OracleDataReader _dataReader;
public override Type GetFieldType(int index)
{
Type fieldType = _dataReader.GetProviderSpecificFieldType(index);
if (fieldType != typeof(OracleXmlType) && fieldType != typeof(OracleBlob))
fieldType = _dataReader.GetFieldType(index);
return fieldType;
}
public override object GetValue(object o, int index)
{
Type fieldType = _dataReader.GetProviderSpecificFieldType(index);
if (fieldType == typeof(OracleXmlType))
{
OracleXmlType xml = _dataReader.GetOracleXmlType(index);
return MappingSchema.ConvertToXmlDocument(xml);
}
if (fieldType == typeof(OracleBlob))
{
OracleBlob blob = _dataReader.GetOracleBlob(index);
return MappingSchema.ConvertToStream(blob);
}
return _dataReader.IsDBNull(index)? null:
_dataReader.GetValue(index);
}
public override Boolean GetBoolean(object o, int index) { return MappingSchema.ConvertToBoolean(GetValue(o, index)); }
public override Char GetChar (object o, int index) { return MappingSchema.ConvertToChar (GetValue(o, index)); }
public override Guid GetGuid (object o, int index) { return MappingSchema.ConvertToGuid (GetValue(o, index)); }
[CLSCompliant(false)]
public override SByte GetSByte (object o, int index) { return (SByte)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt16 GetUInt16 (object o, int index) { return (UInt16)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt32 GetUInt32 (object o, int index) { return (UInt32)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt64 GetUInt64 (object o, int index) { return (UInt64)_dataReader.GetDecimal(index); }
public override Decimal GetDecimal(object o, int index) { return OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(index), 28).Value; }
public override Boolean? GetNullableBoolean(object o, int index) { return MappingSchema.ConvertToNullableBoolean(GetValue(o, index)); }
public override Char? GetNullableChar (object o, int index) { return MappingSchema.ConvertToNullableChar (GetValue(o, index)); }
public override Guid? GetNullableGuid (object o, int index) { return MappingSchema.ConvertToNullableGuid (GetValue(o, index)); }
[CLSCompliant(false)]
public override SByte? GetNullableSByte (object o, int index) { return _dataReader.IsDBNull(index)? null: (SByte?)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt16? GetNullableUInt16 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt16?)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt32? GetNullableUInt32 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt32?)_dataReader.GetDecimal(index); }
[CLSCompliant(false)]
public override UInt64? GetNullableUInt64 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt64?)_dataReader.GetDecimal(index); }
public override Decimal? GetNullableDecimal(object o, int index) { return _dataReader.IsDBNull(index)? (decimal?)null: OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(index), 28).Value; }
}
public class OracleScalarDataReaderMapper : ScalarDataReaderMapper
{
private readonly OracleDataReader _dataReader;
public OracleScalarDataReaderMapper(
MappingSchema mappingSchema,
IDataReader dataReader,
NameOrIndexParameter nameOrIndex)
: base(mappingSchema, dataReader, nameOrIndex)
{
#if FW3
_dataReader = dataReader is OracleDataReaderEx?
((OracleDataReaderEx)dataReader).DataReader:
(OracleDataReader)dataReader;
#else
_dataReader = (OracleDataReader)dataReader;
#endif
_fieldType = _dataReader.GetProviderSpecificFieldType(Index);
if (_fieldType != typeof(OracleXmlType) && _fieldType != typeof(OracleBlob))
_fieldType = _dataReader.GetFieldType(Index);
}
private readonly Type _fieldType;
public override Type GetFieldType(int index)
{
return _fieldType;
}
public override object GetValue(object o, int index)
{
if (_fieldType == typeof(OracleXmlType))
{
OracleXmlType xml = _dataReader.GetOracleXmlType(Index);
return MappingSchema.ConvertToXmlDocument(xml);
}
if (_fieldType == typeof(OracleBlob))
{
OracleBlob blob = _dataReader.GetOracleBlob(Index);
return MappingSchema.ConvertToStream(blob);
}
return _dataReader.IsDBNull(index)? null:
_dataReader.GetValue(Index);
}
public override Boolean GetBoolean(object o, int index) { return MappingSchema.ConvertToBoolean(GetValue(o, Index)); }
public override Char GetChar (object o, int index) { return MappingSchema.ConvertToChar (GetValue(o, Index)); }
public override Guid GetGuid (object o, int index) { return MappingSchema.ConvertToGuid (GetValue(o, Index)); }
[CLSCompliant(false)]
public override SByte GetSByte (object o, int index) { return (SByte)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt16 GetUInt16 (object o, int index) { return (UInt16)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt32 GetUInt32 (object o, int index) { return (UInt32)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt64 GetUInt64 (object o, int index) { return (UInt64)_dataReader.GetDecimal(Index); }
public override Decimal GetDecimal(object o, int index) { return OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(Index), 28).Value; }
public override Boolean? GetNullableBoolean(object o, int index) { return MappingSchema.ConvertToNullableBoolean(GetValue(o, Index)); }
public override Char? GetNullableChar (object o, int index) { return MappingSchema.ConvertToNullableChar (GetValue(o, Index)); }
public override Guid? GetNullableGuid (object o, int index) { return MappingSchema.ConvertToNullableGuid (GetValue(o, Index)); }
[CLSCompliant(false)]
public override SByte? GetNullableSByte (object o, int index) { return _dataReader.IsDBNull(index)? null: (SByte?)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt16? GetNullableUInt16 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt16?)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt32? GetNullableUInt32 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt32?)_dataReader.GetDecimal(Index); }
[CLSCompliant(false)]
public override UInt64? GetNullableUInt64 (object o, int index) { return _dataReader.IsDBNull(index)? null: (UInt64?)_dataReader.GetDecimal(Index); }
public override Decimal? GetNullableDecimal(object o, int index) { return _dataReader.IsDBNull(index)? (decimal?)null: OracleDecimal.SetPrecision(_dataReader.GetOracleDecimal(Index), 28).Value; }
}
[Mixin(typeof(IDbDataParameter), "_oracleParameter")]
[Mixin(typeof(IDataParameter), "_oracleParameter")]
[Mixin(typeof(IDisposable), "_oracleParameter")]
[Mixin(typeof(ICloneable), "_oracleParameter")]
[CLSCompliant(false)]
public abstract class OracleParameterWrap
{
protected OracleParameter _oracleParameter;
public OracleParameter OracleParameter
{
get { return _oracleParameter; }
}
public static IDbDataParameter CreateInstance(OracleParameter oraParameter)
{
OracleParameterWrap wrap = TypeAccessor<OracleParameterWrap>.CreateInstanceEx();
wrap._oracleParameter = oraParameter;
return (IDbDataParameter)wrap;
}
public override string ToString()
{
return _oracleParameter.ToString();
}
///<summary>
///Gets or sets the value of the parameter.
///</summary>
///<returns>
///An <see cref="T:System.Object"/> that is the value of the parameter.
///The default value is null.
///</returns>
protected object Value
{
#if CONVERTORACLETYPES
[MixinOverride]
get
{
object value = _oracleParameter.Value;
if (value is OracleBinary)
{
OracleBinary oracleValue = (OracleBinary)value;
return oracleValue.IsNull? null: oracleValue.Value;
}
if (value is OracleDate)
{
OracleDate oracleValue = (OracleDate)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleDecimal)
{
OracleDecimal oracleValue = (OracleDecimal)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleIntervalDS)
{
OracleIntervalDS oracleValue = (OracleIntervalDS)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleIntervalYM)
{
OracleIntervalYM oracleValue = (OracleIntervalYM)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleString)
{
OracleString oracleValue = (OracleString)value;
return oracleValue.IsNull? null: oracleValue.Value;
}
if (value is OracleTimeStamp)
{
OracleTimeStamp oracleValue = (OracleTimeStamp)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleTimeStampLTZ)
{
OracleTimeStampLTZ oracleValue = (OracleTimeStampLTZ)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleTimeStampTZ)
{
OracleTimeStampTZ oracleValue = (OracleTimeStampTZ)value;
if (oracleValue.IsNull)
return null;
return oracleValue.Value;
}
if (value is OracleXmlType)
{
OracleXmlType oracleValue = (OracleXmlType)value;
return oracleValue.IsNull? null: oracleValue.Value;
}
return value;
}
#endif
[MixinOverride]
set
{
if (null != value)
{
if (value is Guid)
{
// Fix Oracle.Net bug #6: guid type is not handled
//
value = ((Guid)value).ToByteArray();
}
else if (value is Array && !(value is byte[] || value is char[]))
{
_oracleParameter.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
}
else if (value is IConvertible)
{
IConvertible convertible = (IConvertible)value;
TypeCode typeCode = convertible.GetTypeCode();
switch (typeCode)
{
case TypeCode.Boolean:
// Fix Oracle.Net bug #7: bool type is handled wrong
//
value = convertible.ToByte(null);
break;
case TypeCode.SByte:
case TypeCode.UInt16:
case TypeCode.UInt32:
case TypeCode.UInt64:
// Fix Oracle.Net bug #8: some integer types are handled wrong
//
value = convertible.ToDecimal(null);
break;
// Fix Oracle.Net bug #10: zero-length string can not be converted to
// ORAXML type, but null value can be.
//
case TypeCode.String:
if (((string)value).Length == 0)
value = null;
break;
default:
// Fix Oracle.Net bug #5: Enum type is not handled
//
if (value is Enum)
{
// Convert a Enum value to it's underlying type.
//
value = System.Convert.ChangeType(value, typeCode);
}
break;
}
}
}
_oracleParameter.Value = value;
}
}
}
#endregion
}
} |