diff --git a/src/NHibernate/AdoNet/DbDataReaderExtensions.cs b/src/NHibernate/AdoNet/DbDataReaderExtensions.cs new file mode 100644 index 00000000000..9f900fe9099 --- /dev/null +++ b/src/NHibernate/AdoNet/DbDataReaderExtensions.cs @@ -0,0 +1,243 @@ +using System; +using System.Data.Common; + +namespace NHibernate.AdoNet +{ + internal static class DbDataReaderExtensions + { + public static bool TryGetBoolean(this DbDataReader rs, int ordinal, out bool value) + { + try + { + value = rs.GetBoolean(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetByte(this DbDataReader rs, int ordinal, out byte value) + { + try + { + value = rs.GetByte(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetChar(this DbDataReader rs, int ordinal, out char value) + { + try + { + value = rs.GetChar(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetDecimal(this DbDataReader rs, int ordinal, out decimal value) + { + try + { + value = rs.GetDecimal(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetDouble(this DbDataReader rs, int ordinal, out double value) + { + try + { + value = rs.GetDouble(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetDateTime(this DbDataReader rs, int ordinal, out DateTime value) + { + try + { + value = rs.GetDateTime(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + public static bool TryGetFloat(this DbDataReader rs, int ordinal, out float value) + { + try + { + value = rs.GetFloat(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + public static bool TryGetGuid(this DbDataReader rs, int ordinal, out Guid value) + { + try + { + value = rs.GetGuid(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetUInt16(this DbDataReader rs, int ordinal, out ushort value) + { + var dbValue = rs[ordinal]; + + if (dbValue is ushort) + { + value = (ushort) dbValue; + return true; + } + + value = default; + return false; + } + + public static bool TryGetInt16(this DbDataReader rs, int ordinal, out short value) + { + try + { + value = rs.GetInt16(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + public static bool TryGetInt32(this DbDataReader rs, int ordinal, out int value) + { + try + { + value = rs.GetInt32(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetUInt32(this DbDataReader rs, int ordinal, out uint value) + { + var dbValue = rs[ordinal]; + + if (dbValue is uint) + { + value = (uint) dbValue; + return true; + } + + value = default; + return false; + } + + public static bool TryGetInt64(this DbDataReader rs, int ordinal, out long value) + { + try + { + value = rs.GetInt64(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetUInt64(this DbDataReader rs, int ordinal, out ulong value) + { + var dbValue = rs[ordinal]; + + if (dbValue is ulong) + { + value = (ulong) dbValue; + return true; + } + + value = default; + return false; + } + + public static bool TryGetSByte(this DbDataReader rs, int ordinal, out sbyte value) + { + var dbValue = rs[ordinal]; + + if (dbValue is sbyte) + { + value = (sbyte) rs[ordinal]; + return true; + } + + value = default; + return false; + } + + public static bool TryGetString(this DbDataReader rs, int ordinal, out string value) + { + try + { + value = rs.GetString(ordinal); + return true; + } + catch (InvalidCastException) + { + value = default; + return false; + } + } + + public static bool TryGetTimeSpan(this DbDataReader rs, int ordinal, out TimeSpan value) + { + var dbValue = rs[ordinal]; + + if (dbValue is TimeSpan) + { + value = (TimeSpan) dbValue; + return true; + } + + value = default; + return false; + } + } +} diff --git a/src/NHibernate/Async/Type/AbstractDateTimeType.cs b/src/NHibernate/Async/Type/AbstractDateTimeType.cs index 827ac034995..2265da31919 100644 --- a/src/NHibernate/Async/Type/AbstractDateTimeType.cs +++ b/src/NHibernate/Async/Type/AbstractDateTimeType.cs @@ -13,6 +13,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Globalization; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/ByteType.cs b/src/NHibernate/Async/Type/ByteType.cs index 0d38fdf1a71..bc2c01e193e 100644 --- a/src/NHibernate/Async/Type/ByteType.cs +++ b/src/NHibernate/Async/Type/ByteType.cs @@ -13,6 +13,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/Int16Type.cs b/src/NHibernate/Async/Type/Int16Type.cs index 598f83c5aa5..3f35f525f6d 100644 --- a/src/NHibernate/Async/Type/Int16Type.cs +++ b/src/NHibernate/Async/Type/Int16Type.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Data; using System.Numerics; +using NHibernate.AdoNet; namespace NHibernate.Type { diff --git a/src/NHibernate/Async/Type/Int32Type.cs b/src/NHibernate/Async/Type/Int32Type.cs index 3b4217968dd..43f736e3a99 100644 --- a/src/NHibernate/Async/Type/Int32Type.cs +++ b/src/NHibernate/Async/Type/Int32Type.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Data; using System.Numerics; +using NHibernate.AdoNet; namespace NHibernate.Type { diff --git a/src/NHibernate/Async/Type/Int64Type.cs b/src/NHibernate/Async/Type/Int64Type.cs index e1b07967cbd..4ed4d25cbb5 100644 --- a/src/NHibernate/Async/Type/Int64Type.cs +++ b/src/NHibernate/Async/Type/Int64Type.cs @@ -14,6 +14,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/TicksType.cs b/src/NHibernate/Async/Type/TicksType.cs index 0ffb06b37f6..c239faf2c88 100644 --- a/src/NHibernate/Async/Type/TicksType.cs +++ b/src/NHibernate/Async/Type/TicksType.cs @@ -11,6 +11,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/TimeAsTimeSpanType.cs b/src/NHibernate/Async/Type/TimeAsTimeSpanType.cs index 185baa88eba..08aedfa9381 100644 --- a/src/NHibernate/Async/Type/TimeAsTimeSpanType.cs +++ b/src/NHibernate/Async/Type/TimeAsTimeSpanType.cs @@ -15,6 +15,7 @@ using NHibernate.SqlTypes; using System.Collections.Generic; using System.Data; +using NHibernate.AdoNet; namespace NHibernate.Type { diff --git a/src/NHibernate/Async/Type/TimeSpanType.cs b/src/NHibernate/Async/Type/TimeSpanType.cs index 0917413671c..b5d7339ef79 100644 --- a/src/NHibernate/Async/Type/TimeSpanType.cs +++ b/src/NHibernate/Async/Type/TimeSpanType.cs @@ -15,6 +15,7 @@ using NHibernate.SqlTypes; using System.Collections.Generic; using System.Data; +using NHibernate.AdoNet; namespace NHibernate.Type { diff --git a/src/NHibernate/Async/Type/UInt16Type.cs b/src/NHibernate/Async/Type/UInt16Type.cs index cfd05ee60f6..7d3a63d3a55 100644 --- a/src/NHibernate/Async/Type/UInt16Type.cs +++ b/src/NHibernate/Async/Type/UInt16Type.cs @@ -14,6 +14,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/UInt32Type.cs b/src/NHibernate/Async/Type/UInt32Type.cs index 2fa37d01162..5ff4642c8da 100644 --- a/src/NHibernate/Async/Type/UInt32Type.cs +++ b/src/NHibernate/Async/Type/UInt32Type.cs @@ -14,6 +14,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/UInt64Type.cs b/src/NHibernate/Async/Type/UInt64Type.cs index d2db5e47c99..629f981f4cc 100644 --- a/src/NHibernate/Async/Type/UInt64Type.cs +++ b/src/NHibernate/Async/Type/UInt64Type.cs @@ -14,6 +14,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/UriType.cs b/src/NHibernate/Async/Type/UriType.cs index ff7e316ffd1..49013ef70c7 100644 --- a/src/NHibernate/Async/Type/UriType.cs +++ b/src/NHibernate/Async/Type/UriType.cs @@ -10,6 +10,7 @@ using System; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/XDocType.cs b/src/NHibernate/Async/Type/XDocType.cs index 72da2d2b271..2c1c6191a0e 100644 --- a/src/NHibernate/Async/Type/XDocType.cs +++ b/src/NHibernate/Async/Type/XDocType.cs @@ -11,6 +11,7 @@ using System; using System.Data.Common; using System.Xml.Linq; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Async/Type/XmlDocType.cs b/src/NHibernate/Async/Type/XmlDocType.cs index 87da089118a..9a0e550d4ae 100644 --- a/src/NHibernate/Async/Type/XmlDocType.cs +++ b/src/NHibernate/Async/Type/XmlDocType.cs @@ -11,6 +11,7 @@ using System; using System.Data.Common; using System.Xml; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Type/AbstractCharType.cs b/src/NHibernate/Type/AbstractCharType.cs index ba2ad5bb761..879640bf3be 100644 --- a/src/NHibernate/Type/AbstractCharType.cs +++ b/src/NHibernate/Type/AbstractCharType.cs @@ -1,5 +1,6 @@ using System; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -20,12 +21,24 @@ public AbstractCharType(SqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - string dbValue = Convert.ToString(rs[index]); + if (rs.TryGetChar(index, out var dbValue)) + { + return dbValue; + } + + if (!rs.TryGetString(index, out var strValue)) + { + var locale = session.Factory.Settings.Locale; + + strValue = Convert.ToString(rs[index], locale); + } + // The check of the Length is a workaround see NH-2340 - if (dbValue.Length > 0) + if (strValue.Length > 0) { - return dbValue[0]; + return strValue[0]; } + return '\0'; // This line should never be executed } diff --git a/src/NHibernate/Type/AbstractDateTimeType.cs b/src/NHibernate/Type/AbstractDateTimeType.cs index 9deb2273d3e..bf57167de0f 100644 --- a/src/NHibernate/Type/AbstractDateTimeType.cs +++ b/src/NHibernate/Type/AbstractDateTimeType.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Data.Common; using System.Globalization; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -64,7 +65,14 @@ protected virtual DateTime GetDateTime(DbDataReader rs, int index, ISessionImple { try { - return AdjustDateTime(Convert.ToDateTime(rs[index])); + if (!rs.TryGetDateTime(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToDateTime(rs[index], locale); + } + + return AdjustDateTime(dbValue); } catch (Exception ex) { diff --git a/src/NHibernate/Type/AbstractStringType.cs b/src/NHibernate/Type/AbstractStringType.cs index e5c073b7df7..bbecbb24e0d 100644 --- a/src/NHibernate/Type/AbstractStringType.cs +++ b/src/NHibernate/Type/AbstractStringType.cs @@ -1,7 +1,8 @@ -using System; +using System; using System.Collections.Generic; using System.Data.Common; using System.Globalization; +using NHibernate.AdoNet; using NHibernate.Driver; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -73,7 +74,14 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return Convert.ToString(rs[index]); + if (!rs.TryGetString(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToString(rs[index], locale); + } + + return dbValue; } public override bool IsEqual(object x, object y) diff --git a/src/NHibernate/Type/BooleanType.cs b/src/NHibernate/Type/BooleanType.cs index d93e23e0385..423fb0fca68 100644 --- a/src/NHibernate/Type/BooleanType.cs +++ b/src/NHibernate/Type/BooleanType.cs @@ -2,6 +2,7 @@ using System.Data; using System.Data.Common; using System.Runtime.CompilerServices; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -40,7 +41,14 @@ public BooleanType(AnsiStringFixedLengthSqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return GetBooleanAsObject(Convert.ToBoolean(rs[index])); + if (!rs.TryGetBoolean(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToBoolean(rs[index], locale); + } + + return GetBooleanAsObject(dbValue); } public override System.Type PrimitiveClass => typeof(bool); diff --git a/src/NHibernate/Type/ByteType.cs b/src/NHibernate/Type/ByteType.cs index f52071890ff..ba76f2acd3c 100644 --- a/src/NHibernate/Type/ByteType.cs +++ b/src/NHibernate/Type/ByteType.cs @@ -3,6 +3,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -24,11 +25,17 @@ public ByteType() : base(SqlTypeFactory.Byte) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return rs[index] switch + if (rs.TryGetByte(index, out var dbValue)) { + return dbValue; + } + + var locale = session.Factory.Settings.Locale; + return rs[index] switch + { BigInteger bi => (byte) bi, - var c => Convert.ToByte(c) + var c => Convert.ToByte(c, locale) }; } diff --git a/src/NHibernate/Type/CharBooleanType.cs b/src/NHibernate/Type/CharBooleanType.cs index 1224fb363d5..e4db1b41063 100644 --- a/src/NHibernate/Type/CharBooleanType.cs +++ b/src/NHibernate/Type/CharBooleanType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -29,14 +30,20 @@ protected CharBooleanType(AnsiStringFixedLengthSqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - string code = Convert.ToString(rs[index]); - if (code == null) + if (!rs.TryGetString(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToString(rs[index], locale); + } + + if (dbValue == null) { return null; } else { - return GetBooleanAsObject(code.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase)); + return GetBooleanAsObject(dbValue.Equals(TrueString, StringComparison.InvariantCultureIgnoreCase)); } } diff --git a/src/NHibernate/Type/DecimalType.cs b/src/NHibernate/Type/DecimalType.cs index e2398ec4ce6..3ef69f9a4d0 100644 --- a/src/NHibernate/Type/DecimalType.cs +++ b/src/NHibernate/Type/DecimalType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,7 +29,14 @@ public DecimalType(SqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return Convert.ToDecimal(rs[index]); + if (!rs.TryGetDecimal(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToDecimal(rs[index], locale); + } + + return dbValue; } public override System.Type ReturnedClass => typeof(Decimal); diff --git a/src/NHibernate/Type/DoubleType.cs b/src/NHibernate/Type/DoubleType.cs index 45b5713f525..07cd50c0f09 100644 --- a/src/NHibernate/Type/DoubleType.cs +++ b/src/NHibernate/Type/DoubleType.cs @@ -2,6 +2,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,10 +29,17 @@ public DoubleType(SqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetDouble(index, out var dbValue)) + { + return dbValue; + } + + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (double) bi, - var v => Convert.ToDouble(v) + var v => Convert.ToDouble(v, locale) }; } diff --git a/src/NHibernate/Type/GuidType.cs b/src/NHibernate/Type/GuidType.cs index 2dc627d5d09..fc96faf9d4b 100644 --- a/src/NHibernate/Type/GuidType.cs +++ b/src/NHibernate/Type/GuidType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -22,9 +23,9 @@ public GuidType() : base(SqlTypeFactory.Guid) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - if (rs.GetFieldType(index) == typeof (Guid)) + if (rs.TryGetGuid(index, out var dbValue)) { - return rs.GetGuid(index); + return dbValue; } if (rs.GetFieldType(index) == typeof(byte[])) @@ -32,7 +33,14 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi return new Guid((byte[])(rs[index])); } - return new Guid(Convert.ToString(rs[index])); + if (!rs.TryGetString(index, out var dbString)) + { + var locale = session.Factory.Settings.Locale; + + dbString = Convert.ToString(rs[index], locale); + } + + return new Guid(dbString); } /// diff --git a/src/NHibernate/Type/Int16Type.cs b/src/NHibernate/Type/Int16Type.cs index cfd21908465..b090fe153bc 100644 --- a/src/NHibernate/Type/Int16Type.cs +++ b/src/NHibernate/Type/Int16Type.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Data; using System.Numerics; +using NHibernate.AdoNet; namespace NHibernate.Type { @@ -28,12 +29,19 @@ public Int16Type() : base(SqlTypeFactory.Int16) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetInt16(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (short) bi, - var c => Convert.ToInt16(c) + var c => Convert.ToInt16(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/Int32Type.cs b/src/NHibernate/Type/Int32Type.cs index f19fb1148fd..3c8cbf7ff21 100644 --- a/src/NHibernate/Type/Int32Type.cs +++ b/src/NHibernate/Type/Int32Type.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Data; using System.Numerics; +using NHibernate.AdoNet; namespace NHibernate.Type { @@ -28,12 +29,19 @@ public Int32Type() : base(SqlTypeFactory.Int32) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetInt32(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (int) bi, - var c => Convert.ToInt32(c) + var c => Convert.ToInt32(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/Int64Type.cs b/src/NHibernate/Type/Int64Type.cs index b86cb619443..4e2b3deb6b0 100644 --- a/src/NHibernate/Type/Int64Type.cs +++ b/src/NHibernate/Type/Int64Type.cs @@ -4,6 +4,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,12 +29,19 @@ public Int64Type() : base(SqlTypeFactory.Int64) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetInt64(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (long) bi, - var c => Convert.ToInt64(c) + var c => Convert.ToInt64(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/SByteType.cs b/src/NHibernate/Type/SByteType.cs index 513cacb6e70..817c714a316 100644 --- a/src/NHibernate/Type/SByteType.cs +++ b/src/NHibernate/Type/SByteType.cs @@ -4,6 +4,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,12 +29,19 @@ public SByteType() : base(SqlTypeFactory.SByte) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetSByte(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (sbyte) bi, - var c => Convert.ToSByte(c) + var c => Convert.ToSByte(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/SingleType.cs b/src/NHibernate/Type/SingleType.cs index a5d56ce9ade..d5fffec0d84 100644 --- a/src/NHibernate/Type/SingleType.cs +++ b/src/NHibernate/Type/SingleType.cs @@ -2,6 +2,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -34,12 +35,19 @@ public SingleType(SqlType sqlType) : base(sqlType) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetFloat(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (float) bi, - var v => Convert.ToSingle(v) + var v => Convert.ToSingle(v, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/TicksType.cs b/src/NHibernate/Type/TicksType.cs index 4fc18a007cd..f21d534365b 100644 --- a/src/NHibernate/Type/TicksType.cs +++ b/src/NHibernate/Type/TicksType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; diff --git a/src/NHibernate/Type/TimeAsTimeSpanType.cs b/src/NHibernate/Type/TimeAsTimeSpanType.cs index f5218c0775c..2d47923e26f 100644 --- a/src/NHibernate/Type/TimeAsTimeSpanType.cs +++ b/src/NHibernate/Type/TimeAsTimeSpanType.cs @@ -1,10 +1,11 @@ -using System; +using System; using System.Collections; using System.Data.Common; using NHibernate.Engine; using NHibernate.SqlTypes; using System.Collections.Generic; using System.Data; +using NHibernate.AdoNet; namespace NHibernate.Type { @@ -35,14 +36,19 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi { try { - var value = rs[index]; - if (value is TimeSpan time) //For those dialects where DbType.Time means TimeSpan. - return time; - - // Todo: investigate if this convert should be made culture invariant, here and in other NHibernate types, - // such as AbstractDateTimeType and TimeType, or even in all other places doing such converts in NHibernate. - var dbValue = Convert.ToDateTime(value); - return dbValue.TimeOfDay; + if (rs.TryGetTimeSpan(index, out var dbTimeSpan)) + { + return dbTimeSpan; + } + + if (!rs.TryGetDateTime(index, out var dbDateTime)) + { + var locale = session.Factory.Settings.Locale; + + dbDateTime = Convert.ToDateTime(rs[index], locale); + } + + return dbDateTime.TimeOfDay; } catch (Exception ex) { diff --git a/src/NHibernate/Type/TimeSpanType.cs b/src/NHibernate/Type/TimeSpanType.cs index ed37b4629d2..08d80399b18 100644 --- a/src/NHibernate/Type/TimeSpanType.cs +++ b/src/NHibernate/Type/TimeSpanType.cs @@ -5,6 +5,7 @@ using NHibernate.SqlTypes; using System.Collections.Generic; using System.Data; +using NHibernate.AdoNet; namespace NHibernate.Type { @@ -27,7 +28,14 @@ public override object Get(DbDataReader rs, int index, ISessionImplementor sessi { try { - return new TimeSpan(Convert.ToInt64(rs[index])); + if (!rs.TryGetInt64(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToInt64(rs[index], locale); + } + + return new TimeSpan(dbValue); } catch (Exception ex) { diff --git a/src/NHibernate/Type/TimeType.cs b/src/NHibernate/Type/TimeType.cs index c095ef0c0d2..14a53e97c08 100644 --- a/src/NHibernate/Type/TimeType.cs +++ b/src/NHibernate/Type/TimeType.cs @@ -1,6 +1,7 @@ using System; using System.Data; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -50,20 +51,26 @@ public override string Name public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - try + if (rs.TryGetTimeSpan(index, out var dbTimeSpan)) { - if (rs[index] is TimeSpan time) //For those dialects where DbType.Time means TimeSpan. - { - return BaseDateValue.AddTicks(time.Ticks); - } - - DateTime dbValue = Convert.ToDateTime(rs[index]); - return BaseDateValue.Add(dbValue.TimeOfDay); + return BaseDateValue.AddTicks(dbTimeSpan.Ticks); } - catch (Exception ex) + + if (!rs.TryGetDateTime(index, out var dbDateTime)) { - throw new FormatException(string.Format("Input string '{0}' was not in the correct format.", rs[index]), ex); + try + { + var locale = session.Factory.Settings.Locale; + + dbDateTime = Convert.ToDateTime(rs[index], locale); + } + catch (Exception ex) + { + throw new FormatException(string.Format("Input string '{0}' was not in the correct format.", rs[index]), ex); + } } + + return BaseDateValue.Add(dbDateTime.TimeOfDay); } public override System.Type ReturnedClass diff --git a/src/NHibernate/Type/UInt16Type.cs b/src/NHibernate/Type/UInt16Type.cs index c37bbfaca75..398ad3818b9 100644 --- a/src/NHibernate/Type/UInt16Type.cs +++ b/src/NHibernate/Type/UInt16Type.cs @@ -4,6 +4,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,12 +29,19 @@ public UInt16Type() : base(SqlTypeFactory.UInt16) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetUInt16(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (ushort) bi, - var c => Convert.ToUInt16(c) + var c => Convert.ToUInt16(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/UInt32Type.cs b/src/NHibernate/Type/UInt32Type.cs index e0e30b65f2f..6f95f96942e 100644 --- a/src/NHibernate/Type/UInt32Type.cs +++ b/src/NHibernate/Type/UInt32Type.cs @@ -4,6 +4,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -28,12 +29,19 @@ public UInt32Type() : base(SqlTypeFactory.UInt32) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetUInt32(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (uint) bi, - var c => Convert.ToUInt32(c) + var c => Convert.ToUInt32(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/UInt64Type.cs b/src/NHibernate/Type/UInt64Type.cs index 8d0c05d20b1..abc4d86dfa2 100644 --- a/src/NHibernate/Type/UInt64Type.cs +++ b/src/NHibernate/Type/UInt64Type.cs @@ -4,6 +4,7 @@ using System.Data; using System.Data.Common; using System.Numerics; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -27,12 +28,19 @@ public UInt64Type() : base(SqlTypeFactory.UInt64) public override object Get(DbDataReader rs, int index, ISessionImplementor session) { + if (rs.TryGetUInt64(index, out var dbValue)) + { + return dbValue; + } + try { + var locale = session.Factory.Settings.Locale; + return rs[index] switch { BigInteger bi => (ulong)bi, - var c => Convert.ToUInt64(c) + var c => Convert.ToUInt64(c, locale) }; } catch (Exception ex) diff --git a/src/NHibernate/Type/UriType.cs b/src/NHibernate/Type/UriType.cs index 48fbe91a9c8..f1b17527019 100644 --- a/src/NHibernate/Type/UriType.cs +++ b/src/NHibernate/Type/UriType.cs @@ -1,5 +1,6 @@ using System; using System.Data.Common; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -51,7 +52,14 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - return StringToObject(Convert.ToString(rs[index])); + if (!rs.TryGetString(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + dbValue = Convert.ToString(rs[index], locale); + } + + return StringToObject(dbValue); } /// diff --git a/src/NHibernate/Type/XDocType.cs b/src/NHibernate/Type/XDocType.cs index 69912c8ec77..197123d76b8 100644 --- a/src/NHibernate/Type/XDocType.cs +++ b/src/NHibernate/Type/XDocType.cs @@ -1,6 +1,7 @@ using System; using System.Data.Common; using System.Xml.Linq; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -38,12 +39,18 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme /// public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - // according to documentation, GetValue should return a string, at least for MsSQL - // hopefully all DataProvider has the same behaviour - string xmlString = Convert.ToString(rs.GetValue(index)); + if (!rs.TryGetString(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + // according to documentation, GetValue should return a string, at least for MsSQL + // hopefully all DataProvider has the same behaviour + dbValue = Convert.ToString(rs.GetValue(index), locale); + } + // 6.0 TODO: inline the call. #pragma warning disable 618 - return FromStringValue(xmlString); + return FromStringValue(dbValue); #pragma warning restore 618 } diff --git a/src/NHibernate/Type/XmlDocType.cs b/src/NHibernate/Type/XmlDocType.cs index d4b26317f29..f66bd08b2c8 100644 --- a/src/NHibernate/Type/XmlDocType.cs +++ b/src/NHibernate/Type/XmlDocType.cs @@ -1,6 +1,7 @@ using System; using System.Data.Common; using System.Xml; +using NHibernate.AdoNet; using NHibernate.Engine; using NHibernate.SqlTypes; @@ -37,12 +38,18 @@ public override void Set(DbCommand cmd, object value, int index, ISessionImpleme /// public override object Get(DbDataReader rs, int index, ISessionImplementor session) { - // according to documentation, GetValue should return a string, at least for MsSQL - // hopefully all DataProvider has the same behaviour - string xmlString = Convert.ToString(rs.GetValue(index)); + if (!rs.TryGetString(index, out var dbValue)) + { + var locale = session.Factory.Settings.Locale; + + // according to documentation, GetValue should return a string, at least for MsSQL + // hopefully all DataProvider has the same behaviour + dbValue = Convert.ToString(rs.GetValue(index), locale); + } + // 6.0 TODO: inline the call. #pragma warning disable 618 - return FromStringValue(xmlString); + return FromStringValue(dbValue); #pragma warning restore 618 }