diff --git a/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj b/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
index 74f5fe5..3433e01 100644
--- a/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
+++ b/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
@@ -3,7 +3,7 @@
false
- netstandard2.0;net452
+ netstandard2.0;net461
true
key.snk
@@ -24,6 +24,6 @@
- v4.5.2
+ v4.6.1
\ No newline at end of file
diff --git a/src/Dapper.Oracle/Dapper.Oracle.StrongName.csproj b/src/Dapper.Oracle/Dapper.Oracle.StrongName.csproj
index 0771ca4..29c5201 100644
--- a/src/Dapper.Oracle/Dapper.Oracle.StrongName.csproj
+++ b/src/Dapper.Oracle/Dapper.Oracle.StrongName.csproj
@@ -3,7 +3,7 @@
false
- netstandard2.0;net452
+ netstandard2.0;net461
@@ -11,13 +11,14 @@
+
-
+
- v4.5.2
+ v4.6.1
\ No newline at end of file
diff --git a/src/Dapper.Oracle/Dapper.Oracle.csproj b/src/Dapper.Oracle/Dapper.Oracle.csproj
index c8944b0..06c0807 100644
--- a/src/Dapper.Oracle/Dapper.Oracle.csproj
+++ b/src/Dapper.Oracle/Dapper.Oracle.csproj
@@ -3,7 +3,7 @@
false
- netstandard2.0;net452
+ netstandard2.0;net461
@@ -11,13 +11,14 @@
+
-
+
- v4.5.2
+ v4.6.1
\ No newline at end of file
diff --git a/src/Dapper.Oracle/OracleDynamicParameters.cs b/src/Dapper.Oracle/OracleDynamicParameters.cs
index f113246..d19cda0 100644
--- a/src/Dapper.Oracle/OracleDynamicParameters.cs
+++ b/src/Dapper.Oracle/OracleDynamicParameters.cs
@@ -157,7 +157,7 @@ public IEnumerable ParameterNames
/// The value, note DBNull.Value is not returned, instead the value is returned as null
public T Get(string name)
{
- var paramInfo = Parameters[Clean(name)];
+ var paramInfo = GetParameter(name);
var attachedParam = paramInfo.AttachedParam;
object val = attachedParam == null ? paramInfo.Value : attachedParam.Value;
if (val == DBNull.Value)
@@ -174,7 +174,7 @@ public T Get(string name)
public OracleParameterInfo GetParameter(string name)
{
- return OracleMethodHelper.GetParameterInfo(Parameters[Clean(name)].AttachedParam);
+ return Parameters[Clean(name)];
}
void SqlMapper.IDynamicParameters.AddParameters(IDbCommand command, SqlMapper.Identity identity)
diff --git a/src/Dapper.Oracle/OracleValueConverter.cs b/src/Dapper.Oracle/OracleValueConverter.cs
index c691695..006d6ca 100644
--- a/src/Dapper.Oracle/OracleValueConverter.cs
+++ b/src/Dapper.Oracle/OracleValueConverter.cs
@@ -1,73 +1,88 @@
using System;
using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data.Common;
using System.Linq;
+using System.Reflection.Emit;
using System.Text.RegularExpressions;
namespace Dapper.Oracle
{
internal static class OracleValueConverter
{
- private static string[] OracleStringTypes { get; } = { "Oracle.DataAccess.Types.OracleString", "Oracle.ManagedDataAccess.Types.OracleString" };
-
- public static T Convert(object val)
+ ///
+ /// Convert the value to the provided generic type.
+ ///
+ ///
+ ///
+ ///
+ public static T Convert(object value)
{
- if (val == null)
+ value = GetValue(value);
+
+ if (value == null || value == DBNull.Value)
{
return default(T);
}
- if (val == DBNull.Value)
+ // Convert the Oracle native data type to .NET data type.
+ // See: https://docs.oracle.com/en/database/oracle/oracle-database/19/clrnt/datatype-conversion.html#GUID-70A2F34D-AB7F-4E0C-89C9-452A45FF1CAC
+ if (value is IConvertible)
{
- if (default(T) != null)
- {
- throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!");
- }
-
- return default(T);
+ var nullableType = Nullable.GetUnderlyingType(typeof(T));
+ return (T)System.Convert.ChangeType(value, nullableType ?? typeof(T));
}
- Type valueType = val.GetType();
- if (typeof(T) == typeof(string) && OracleStringTypes.Contains(valueType.FullName))
- {
- // Need this, because... you know,Oracle...
- val = val.ToString();
+ return default(T);
+ }
- if ((string)val == "null") // Seriously. W.T.F ????
- {
- return default(T);
- }
+ ///
+ /// Gets the underlying primitive value from a nested type instance.
+ ///
+ ///
+ ///
+ private static object GetValue(object value)
+ {
+ if (value == null || value == DBNull.Value)
+ {
+ return null;
+ }
- return (T)val;
+ // Recursively handle nested database parameters.
+ // An OracleParameter can have a value that is an instance of an Oracle data structure (OracleBlob, OracleDecimal, etc.).
+ // This assumes we want the underlying primitive value of the parameter.
+ while (value is DbParameter parameter)
+ {
+ value = parameter.Value;
}
- // We need this, because, you know, Oracle. OracleDecimal,OracleFloat,OracleYaddiAddy,OracleYourUncle etc value types.
- if (Regex.IsMatch(valueType.FullName, @"Oracle\.\w+\.Types\.Oracle\w+"))
+ Type valueType = value.GetType();
+
+ if (IsOracleDataStructure(valueType))
{
- // Fix Oracle 11g (to not throw the exception "Invalid operation on null data" if a function returns NULL)
- var isNullProperty = valueType.GetProperty("IsNull");
- if (isNullProperty != null && isNullProperty.CanRead)
- {
- var isNull = (bool)isNullProperty.GetValue(val);
- if (isNull)
- {
- if (default(T) != null)
- {
- throw new ApplicationException("Attempting to cast a DBNull to a non nullable type!");
- }
- return default(T);
- }
- // If not isNull, continue and get the Value
- }
+ var isNull = (bool)valueType.GetProperty("IsNull", typeof(bool))?.GetValue(value);
- var valueProperty = valueType.GetProperty("Value");
- if (valueProperty != null && valueProperty.CanRead)
+ if (isNull)
{
- object reflected = valueProperty.GetValue(val);
- return (T)reflected;
+ return null;
}
+
+ value = valueType.GetProperty("Value")?.GetValue(value);
}
- return (T)System.Convert.ChangeType(val, typeof(T));
+ return value;
+ }
+
+ ///
+ /// Determine if the type is an Oracle data structure.
+ ///
+ ///
+ ///
+ private static bool IsOracleDataStructure(Type valueType)
+ {
+ // We need this, because, you know, Oracle. OracleDecimal,OracleFloat,OracleYaddiAddy,OracleYourUncle etc value types.
+ // See: https://docs.oracle.com/en/database/oracle/oracle-database/19/odpnt/intro003.html#GUID-425C9EBA-CFFC-47FE-B490-604251714ACA
+ return Regex.IsMatch(valueType.FullName, @"Oracle\.\w+\.Types\.Oracle\w+");
}
}
}
diff --git a/src/Tests.Dapper.Oracle/OracleDynamicParameterTests.cs b/src/Tests.Dapper.Oracle/OracleDynamicParameterTests.cs
index 7fde200..0b7caa3 100644
--- a/src/Tests.Dapper.Oracle/OracleDynamicParameterTests.cs
+++ b/src/Tests.Dapper.Oracle/OracleDynamicParameterTests.cs
@@ -160,5 +160,18 @@ public void GetParameterValue()
testObject.Get("Foo").Should().Be("Bar");
}
+
+ [Fact]
+ public void GetParameter()
+ {
+ testObject.Add("Foo", "Bar", OracleMappingType.Varchar2);
+
+ var param = testObject.GetParameter("Foo");
+
+ param.Should().NotBeNull();
+ param.Name.Should().Be("Foo");
+ param.Value.Should().Be("Bar");
+ param.DbType.Should().Be(OracleMappingType.Varchar2);
+ }
}
}
diff --git a/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs b/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
index 1b39101..52113aa 100644
--- a/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
+++ b/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
@@ -47,32 +47,157 @@ public void GetNullAsStringReturnsNull()
[Fact]
public void GetNullAsDecimalReturns0()
{
- var result = OracleValueConverter.Convert(null);
+ var result = OracleValueConverter.Convert(null);
result.Should().Be(0);
}
[Fact]
- public void GetOracleDecimalReturnsDecimal()
+ public void GetDbNullAsDecimalReturns0()
{
- var result = OracleValueConverter.Convert(new OracleDecimal(100));
- result.Should().Be(100);
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(0);
}
[Fact]
- public void GetOracleDateTimeReturnsDateTime()
+ public void GetNullAsInt32Returns0()
{
- var result = OracleValueConverter.Convert(new OracleDate(DateTime.Today));
- result.Should().Be(DateTime.Today);
+ var result = OracleValueConverter.Convert(null);
+ result.Should().Be(0);
+ }
+
+ [Fact]
+ public void GetDbNullAsInt32Returns0()
+ {
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(0);
+ }
+
+ [Fact]
+ public void GetNullAsInt64Returns0()
+ {
+ var result = OracleValueConverter.Convert(null);
+ result.Should().Be(0);
+ }
+
+ [Fact]
+ public void GetDbNullAsInt64Returns0()
+ {
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(0);
+ }
+
+ [Fact]
+ public void GetNullAsNullableDecimalReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(null);
+ result.Should().BeNull();
+ }
+
+ [Fact]
+ public void GetNullAsNullableInt32ReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(null);
+ result.Should().BeNull();
+ }
+
+ [Fact]
+ public void GetNullAsNullableInt64ReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(null);
+ result.Should().BeNull();
+ }
+
+ [Fact]
+ public void GetDbNullAsDecimalReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(null);
+ }
+
+ [Fact]
+ public void GetDbNullAsInt32ReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(null);
+ }
+
+ [Fact]
+ public void GetDbNullAsInt64ReturnsNull()
+ {
+ var result = OracleValueConverter.Convert(DBNull.Value);
+ result.Should().Be(null);
+ }
+
+
+ [Fact]
+ public void GetOracleDecimalReturnsDecimal()
+ {
+ decimal expected = 100;
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(expected));
+
+ result.Should().Be(expected);
}
[Fact]
- public void GetOracleNumberReturnAsDecimal()
+ public void GetOracleDecimalReturnsNullableDecimal()
{
decimal expected = 100;
- var result = OracleValueConverter.Convert(100);
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(expected));
+
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void GetOracleDecimalReturnsInt32()
+ {
+ decimal input = 100;
+ var expected = Convert.ToInt32(input);
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(input));
+
result.Should().Be(expected);
}
- }
-
+ [Fact]
+ public void GetOracleDecimalReturnsNullableInt32()
+ {
+ decimal input = 100;
+ var expected = Convert.ToInt32(input);
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(input));
+
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void GetOracleDecimalReturnsInt64()
+ {
+ decimal input = 100;
+ var expected = Convert.ToInt64(input);
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(input));
+
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void GetOracleDecimalReturnsNullableInt64()
+ {
+ decimal input = 100;
+ var expected = Convert.ToInt64(input);
+
+ var result = OracleValueConverter.Convert(new OracleDecimal(input));
+
+ result.Should().Be(expected);
+ }
+
+ [Fact]
+ public void GetOracleDateTimeReturnsDateTime()
+ {
+ var result = OracleValueConverter.Convert(new OracleDate(DateTime.Today));
+ result.Should().Be(DateTime.Today);
+ }
+ }
}
diff --git a/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj b/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
index 5942887..68ce5f5 100644
--- a/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
+++ b/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
@@ -9,6 +9,7 @@
+