Mercurial > pub > bltoolkit
diff Source/Data/DataProvider/OdpDataProvider.cs @ 0:f990fcb411a9
Копия текущей версии из github
author | cin |
---|---|
date | Thu, 27 Mar 2014 21:46:09 +0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Data/DataProvider/OdpDataProvider.cs Thu Mar 27 21:46:09 2014 +0400 @@ -0,0 +1,1708 @@ +// Odp.Net Data Provider. +// http://www.oracle.com/technology/tech/windows/odpnet/index.html +// +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.Common; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Xml; + +using BLToolkit.Aspects; +using BLToolkit.Common; +using BLToolkit.Mapping; +using BLToolkit.Reflection; + +#if MANAGED +using Oracle.ManagedDataAccess.Client; +using Oracle.ManagedDataAccess.Types; +#else +using Oracle.DataAccess.Client; +using Oracle.DataAccess.Types; +#endif + +namespace BLToolkit.Data.DataProvider +{ + using Sql.SqlProvider; + using BLToolkit.Data.Sql; + + /// <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> +#if !MANAGED + public class OdpDataProvider : DataProviderBase + { + public OdpDataProvider() + { + MappingSchema = new OdpMappingSchema(); + } + + public const string NameString = DataProvider.ProviderName.Oracle; + + private const string DbTypeTableName = "Oracle.DataAccess.Client.OraDb_DbTypeTable"; + + static OdpDataProvider() + { +#else + public class OdpManagedDataProvider : DataProviderBase + { + public OdpManagedDataProvider() + { + MappingSchema = new OdpMappingSchema(); + } + + public const string NameString = DataProvider.ProviderName.OracleManaged; + + private const string DbTypeTableName = "Oracle.ManagedDataAccess.Client.OraDb_DbTypeTable"; + + static OdpManagedDataProvider() + { +#endif + // Fix Oracle.Net bug #1: Array types are not handled. + // + var oraDbDbTypeTableType = typeof(OracleParameter).Assembly.GetType(DbTypeTableName); + + if (null != oraDbDbTypeTableType) + { + var typeTable = (Hashtable)oraDbDbTypeTableType.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; +#if !MANAGED + typeTable[typeof(OracleXmlType[])] = OracleDbType.XmlType; +#endif + + 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) + { + var oraConnection = connection as OracleConnection; + + if (null != oraConnection) + { + var 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 void SetParameterValue(IDbDataParameter parameter, object value) + { + base.SetParameterValue(parameter, value); + + // strings and byte arrays larger than 4000 bytes may be handled improperly + if (parameter is OracleParameterWrap) + { + const int ThresholdSize = 4000; + if (value is string && Encoding.UTF8.GetBytes((string)value).Length > ThresholdSize) + { + ((OracleParameterWrap)parameter).OracleParameter.OracleDbType = OracleDbType.Clob; + } + else if (value is byte[] && ((byte[])value).Length > ThresholdSize) + { + ((OracleParameterWrap)parameter).OracleParameter.OracleDbType = OracleDbType.Blob; + } + } + } + + public override IDbDataParameter CloneParameter(IDbDataParameter parameter) + { + var oraParameter = (parameter is OracleParameterWrap)? + (parameter as OracleParameterWrap).OracleParameter: parameter as OracleParameter; + + if (null != oraParameter) + { + var 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) + { + var 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) + { + var 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; + } + + /// <summary> + /// Open an <see cref="IDataReader"/> into the given <see cref="OracleRefCursor"/> object + /// </summary> + /// <param name="refCursor">an <see cref="OracleRefCursor"/> to perform GetDataReader() on</param> + /// <returns>The <see cref="IDataReader"/> into the returned by GetDataReader()</returns> + public override IDataReader GetRefCursorDataReader(object refCursor) + { + var oracleRefCursor = refCursor as OracleRefCursor; + + if (oracleRefCursor == null) + throw new ArgumentException("Argument must be of type 'OracleRefCursor'", "refCursor"); + + return oracleRefCursor.GetDataReader(); + } + + public override object Convert(object value, ConvertType convertType) + { + switch (convertType) + { + case ConvertType.NameToCommandParameter: + case ConvertType.NameToSprocParameter: + return ParameterPrefix == null? value: ParameterPrefix + value; + + case ConvertType.SprocParameterToName: + var 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 SqlProvider.Convert(value, convertType); + } + + 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) + { + var 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) + { + var 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) + { + var arrayBindSize = new int[oraParameter.Size]; + + for (var 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[]) + { + var streams = (Stream[]) oraParameter.Value; + + for (var i = 0; i < oraParameter.Size; ++i) + { + if (streams[i] is OracleBFile || streams[i] is OracleBlob || streams[i] is OracleClob +#if !MANAGED + || streams[i] is OracleXmlStream +#endif + ) + { + // Known Oracle type. + // + continue; + } + + streams[i] = CopyStream(streams[i], (OracleCommand)command); + } + } + else if (oraParameter.Value is XmlDocument[]) + { + var xmlDocuments = (XmlDocument[]) oraParameter.Value; + var values = new object[oraParameter.Size]; + + switch (oraParameter.OracleDbType) + { + case OracleDbType.XmlType: +#if !MANAGED + for (var 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; +#else + throw new NotSupportedException(); +#endif + // 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 (var 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 (var i = 0; i < oraParameter.Size; ++i) + { + if (xmlDocuments[i].DocumentElement == null) + values[i] = DBNull.Value; + else + using (var 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; + var arrayBindSize = new int[oraParameter.Size]; + for (var i = 0; i < oraParameter.Size; ++i) + { + arrayBindSize[i] = 1024; + } + + oraParameter.ArrayBindSize = arrayBindSize; + } + else + { + oraParameter.Size = 32767; + } + } + } + else if (oraParameter.Value is Stream) + { + var stream = (Stream) oraParameter.Value; + + if (!(stream is OracleBFile) && !(stream is OracleBlob) && + !(stream is OracleClob) +#if !MANAGED + && !(stream is OracleXmlStream) +#endif + ) + { + oraParameter.Value = CopyStream(stream, (OracleCommand)command); + } + } + else if (oraParameter.Value is Byte[]) + { + var bytes = (Byte[]) oraParameter.Value; + + if (bytes.Length > 32000) + { + oraParameter.Value = CopyStream(bytes, (OracleCommand)command); + } + } + else if (oraParameter.Value is XmlDocument) + { + var xmlDocument = (XmlDocument)oraParameter.Value; + if (xmlDocument.DocumentElement == null) + oraParameter.Value = DBNull.Value; + else + { + + switch (oraParameter.OracleDbType) + { + case OracleDbType.XmlType: +#if !MANAGED + oraParameter.Value = new OracleXmlType((OracleConnection)command.Connection, xmlDocument); + break; +#else + throw new NotSupportedException(); +#endif + + // 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 (var 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(Common.Convert.ToByteArray(stream), cmd); + } + + private static Stream CopyStream(Byte[] bytes, OracleCommand cmd) + { + var ret = new OracleBlob(cmd.Connection); + ret.Write(bytes, 0, bytes.Length); + return ret; + } + + public override bool IsValueParameter(IDbDataParameter parameter) + { + var 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) + { + var parameter = base.CreateParameterObject(command); + + if (parameter is OracleParameter) + parameter = OracleParameterWrap.CreateInstance(parameter as OracleParameter); + + return parameter; + } + + public override IDbDataParameter GetParameter(IDbCommand command, NameOrIndexParameter nameOrIndex) + { + var 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); } + } + + /// <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 int ExecuteArray(IDbCommand command, int iterations) + { + var cmd = (OracleCommand)command; + var oracleParameters = cmd.Parameters.OfType<OracleParameter>().ToArray(); + var oldCollectionTypes = oracleParameters.Select(p => p.CollectionType).ToArray(); + + try + { + foreach (var p in oracleParameters) + { + p.CollectionType = OracleCollectionType.None; + } + + cmd.ArrayBindCount = iterations; + return cmd.ExecuteNonQuery(); + } + finally + { + foreach (var p in oracleParameters.Zip(oldCollectionTypes, (p, t) => new { Param = p, CollectionType = t })) + { + p.Param.CollectionType = p.CollectionType; + } + + cmd.ArrayBindCount = 0; + } + } + + public override ISqlProvider CreateSqlProvider() + { + return new OracleSqlProvider(); + } + + 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) + { + var ts = DataReader.GetOracleTimeStampTZ(i); + return new DateTimeOffset(ts.Value, ts.GetTimeZoneOffset()); + } + } + + 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) + { + var 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); + } + + public override Reflection.Extension.ExtensionList Extensions + { + get { return Map.DefaultSchema.Extensions; } + set { Map.DefaultSchema.Extensions = value; } + } + + #region Convert + + #region Primitive Types + + [CLSCompliant(false)] + public override SByte ConvertToSByte(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultSByteNullValue: (SByte)oraDecimal.Value; + } + + return base.ConvertToSByte(value); + } + + public override Int16 ConvertToInt16(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultInt16NullValue: oraDecimal.ToInt16(); + } + + return base.ConvertToInt16(value); + } + + public override Int32 ConvertToInt32(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultInt32NullValue: oraDecimal.ToInt32(); + } + + return base.ConvertToInt32(value); + } + + public override Int64 ConvertToInt64(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultInt64NullValue: oraDecimal.ToInt64(); + } + + return base.ConvertToInt64(value); + } + + public override Byte ConvertToByte(object value) + { + if (value is OracleDecimal) + { + var 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) + { + var 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) + { + var 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) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultUInt64NullValue: (UInt64)oraDecimal.Value; + } + + return base.ConvertToUInt64(value); + } + + public override Single ConvertToSingle(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultSingleNullValue: oraDecimal.ToSingle(); + } + + return base.ConvertToSingle(value); + } + + public override Double ConvertToDouble(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultDoubleNullValue: oraDecimal.ToDouble(); + } + + return base.ConvertToDouble(value); + } + + public override Boolean ConvertToBoolean(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultBooleanNullValue: (oraDecimal.Value != 0); + } + + return base.ConvertToBoolean(value); + } + + public override DateTime ConvertToDateTime(object value) + { + if (value is OracleDate) + { + var oraDate = (OracleDate)value; + return oraDate.IsNull? DefaultDateTimeNullValue: oraDate.Value; + } + + return base.ConvertToDateTime(value); + } + + public override Decimal ConvertToDecimal(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? DefaultDecimalNullValue: oraDecimal.Value; + } + + return base.ConvertToDecimal(value); + } + + public override Guid ConvertToGuid(object value) + { + if (value is OracleString) + { + var oraString = (OracleString)value; + return oraString.IsNull? DefaultGuidNullValue: new Guid(oraString.Value); + } + + if (value is OracleBlob) + { + using (var 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) + { + var oraString = (OracleString)value; + return oraString.IsNull? DefaultStringNullValue: oraString.Value; + } +#if !MANAGED + if (value is OracleXmlType) + { + var oraXmlType = (OracleXmlType)value; + return oraXmlType.IsNull ? DefaultStringNullValue : oraXmlType.Value; + } +#endif + if (value is OracleClob) + { + using (var oraClob = (OracleClob)value) + return oraClob.IsNull? DefaultStringNullValue: oraClob.Value; + } + + return base.ConvertToString(value); + } + +#if !MANAGED + public override Stream ConvertToStream(object value) + { + if (value is OracleXmlType) + { + var oraXml = (OracleXmlType)value; + return oraXml.IsNull? DefaultStreamNullValue: oraXml.GetStream(); + } + + return base.ConvertToStream(value); + } + + public override XmlReader ConvertToXmlReader(object value) + { + if (value is OracleXmlType) + { + var oraXml = (OracleXmlType)value; + return oraXml.IsNull? DefaultXmlReaderNullValue: oraXml.GetXmlReader(); + } + + return base.ConvertToXmlReader(value); + } + + public override XmlDocument ConvertToXmlDocument(object value) + { + if (value is OracleXmlType) + { + var oraXml = (OracleXmlType)value; + return oraXml.IsNull? DefaultXmlDocumentNullValue: oraXml.GetXmlDocument(); + } + + return base.ConvertToXmlDocument(value); + } +#endif + + public override Byte[] ConvertToByteArray(object value) + { + if (value is OracleBlob) + { + using (var oraBlob = (OracleBlob)value) + return oraBlob.IsNull? null: oraBlob.Value; + } + + if (value is OracleBinary) + { + var oraBinary = (OracleBinary)value; + return oraBinary.IsNull? null: oraBinary.Value; + } + + if (value is OracleBFile) + { + var oraBFile = (OracleBFile)value; + return oraBFile.IsNull? null: oraBFile.Value; + } + + return base.ConvertToByteArray(value); + } + + public override Char[] ConvertToCharArray(object value) + { + if (value is OracleString) + { + var oraString = (OracleString)value; + return oraString.IsNull? null: oraString.Value.ToCharArray(); + } + + if (value is OracleClob) + { + using (var 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) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (SByte?)oraDecimal.Value; + } + + return base.ConvertToNullableSByte(value); + } + + public override Int16? ConvertToNullableInt16(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Int16?)oraDecimal.ToInt16(); + } + + return base.ConvertToNullableInt16(value); + } + + public override Int32? ConvertToNullableInt32(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Int32?)oraDecimal.ToInt32(); + } + + return base.ConvertToNullableInt32(value); + } + + public override Int64? ConvertToNullableInt64(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Int64?)oraDecimal.ToInt64(); + } + + return base.ConvertToNullableInt64(value); + } + + public override Byte? ConvertToNullableByte(object value) + { + if (value is OracleDecimal) + { + var 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) + { + var 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) + { + var 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) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (UInt64?)oraDecimal.Value; + } + + return base.ConvertToNullableUInt64(value); + } + + public override Single? ConvertToNullableSingle(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Single?)oraDecimal.ToSingle(); + } + + return base.ConvertToNullableSingle(value); + } + + public override Double? ConvertToNullableDouble(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Double?)oraDecimal.ToDouble(); + } + + return base.ConvertToNullableDouble(value); + } + + public override Boolean? ConvertToNullableBoolean(object value) + { + if (value is OracleDecimal) + { + var 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) + { + var oraDate = (OracleDate)value; + return oraDate.IsNull? null: (DateTime?)oraDate.Value; + } + + return base.ConvertToNullableDateTime(value); + } + + public override Decimal? ConvertToNullableDecimal(object value) + { + if (value is OracleDecimal) + { + var oraDecimal = (OracleDecimal)value; + return oraDecimal.IsNull? null: (Decimal?)oraDecimal.Value; + } + + return base.ConvertToNullableDecimal(value); + } + + public override Guid? ConvertToNullableGuid(object value) + { + if (value is OracleString) + { + var oraString = (OracleString)value; + return oraString.IsNull? null: (Guid?)new Guid(oraString.Value); + } + + if (value is OracleBlob) + { + using (var 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) + { + var oracleValue = (OracleString)value; + value = oracleValue.IsNull? null: oracleValue.Value; + } + else if (value is OracleDecimal) + { + var oracleValue = (OracleDecimal)value; + if (oracleValue.IsNull) + value = null; + else + value = oracleValue.Value; + } + + return base.MapValueToEnum(value, type); + } + + public override object MapValueToEnum(object value, MemberAccessor ma) + { + if (value is OracleString) + { + var oracleValue = (OracleString)value; + value = oracleValue.IsNull ? null : oracleValue.Value; + } + else if (value is OracleDecimal) + { + var oracleValue = (OracleDecimal)value; + if (oracleValue.IsNull) + value = null; + else + value = oracleValue.Value; + } + + return base.MapValueToEnum(value, ma); + } + + 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: +#if !MANAGED + value is OracleXmlType? ((OracleXmlType) value).IsNull: +#endif + 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) + { + _dataReader = dataReader is OracleDataReaderEx? + ((OracleDataReaderEx)dataReader).DataReader: + (OracleDataReader)dataReader; + } + + private readonly OracleDataReader _dataReader; + + public override Type GetFieldType(int index) + { + var fieldType = _dataReader.GetProviderSpecificFieldType(index); + + if (fieldType != typeof(OracleBlob) +#if !MANAGED + && fieldType != typeof(OracleXmlType) +#endif + ) + fieldType = _dataReader.GetFieldType(index); + + return fieldType; + } + + public override object GetValue(object o, int index) + { + var fieldType = _dataReader.GetProviderSpecificFieldType(index); + +#if !MANAGED + if (fieldType == typeof(OracleXmlType)) + { + var xml = _dataReader.GetOracleXmlType(index); + return MappingSchema.ConvertToXmlDocument(xml); + } +#endif + if (fieldType == typeof(OracleBlob)) + { + var 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) + { + _dataReader = dataReader is OracleDataReaderEx? + ((OracleDataReaderEx)dataReader).DataReader: + (OracleDataReader)dataReader; + + _fieldType = _dataReader.GetProviderSpecificFieldType(Index); + + if (_fieldType != typeof(OracleBlob) +#if !MANAGED + && _fieldType != typeof(OracleXmlType) +#endif + ) + _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 !MANAGED + if (_fieldType == typeof(OracleXmlType)) + { + var xml = _dataReader.GetOracleXmlType(Index); + return MappingSchema.ConvertToXmlDocument(xml); + } +#endif + if (_fieldType == typeof(OracleBlob)) + { + var 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) + { + var 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) + { + var convertible = (IConvertible)value; + var 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 + + #region InsertBatch + + public override int InsertBatch<T>( + DbManager db, + string insertText, + IEnumerable<T> collection, + MemberMapper[] members, + int maxBatchSize, + DbManager.ParameterProvider<T> getParameters) + { + var sb = new StringBuilder(); + var sp = new OracleSqlProvider(); + var pn = 0; + var n = 0; + var cnt = 0; + var str = "\t" + insertText + .Substring(0, insertText.IndexOf(") VALUES (")) + .Substring(7) + .Replace("\r", "") + .Replace("\n", "") + .Replace("\t", " ") + .Replace("( ", "(") + //.Replace(" ", " ") + + ") VALUES ("; + + var parameters = new List<IDbDataParameter>(); + + foreach (var item in collection) + { + if (sb.Length == 0) + sb.AppendLine("INSERT ALL"); + + sb.Append(str); + + foreach (var member in members) + { + var value = member.GetValue(item); + + if (value != null && value.GetType().IsEnum) + value = MappingSchema.MapEnumToValue(value, true); + + if (value is Nullable<DateTime>) + value = ((DateTime?)value).Value; + + if (value is DateTime) + { + var dt = (DateTime)value; + sb.Append(string.Format("to_timestamp('{0:dd.MM.yyyy HH:mm:ss.ffffff}', 'DD.MM.YYYY HH24:MI:SS.FF6')", dt)); + } + else if (value is string && ((string)value).Length >= 2000) + { + var par = db.Parameter("p" + ++pn, value); + parameters.Add(par); + sb.Append(":" + par.ParameterName); + } + else + sp.BuildValue(sb, value); + + sb.Append(", "); + } + + sb.Length -= 2; + sb.AppendLine(")"); + + n++; + + if (n >= maxBatchSize) + { + sb.AppendLine("SELECT * FROM dual"); + + var sql = sb.ToString(); + + if (DbManager.TraceSwitch.TraceInfo) + DbManager.WriteTraceLine("\n" + sql.Replace("\r", ""), DbManager.TraceSwitch.DisplayName); + + cnt += db + .SetCommand(sql, parameters.Count > 0 ? parameters.ToArray() : null) + .ExecuteNonQuery(); + + parameters.Clear(); + pn = 0; + n = 0; + sb.Length = 0; + } + } + + if (n > 0) + { + sb.AppendLine("SELECT * FROM dual"); + + var sql = sb.ToString(); + + if (DbManager.TraceSwitch.TraceInfo) + DbManager.WriteTraceLine("\n" + sql.Replace("\r", ""), DbManager.TraceSwitch.DisplayName); + + cnt += db + .SetCommand(sql, parameters.Count > 0 ? parameters.ToArray() : null) + .ExecuteNonQuery(); + } + + return cnt; + } + + #endregion + } +}