Skip to content

Commit

Permalink
Merge pull request #47 from opejanovic/master
Browse files Browse the repository at this point in the history
Issue #46 - Fixing converting OracleString[], OracleDecimal[] to .NET native data types
  • Loading branch information
epaulsen authored Nov 6, 2020
2 parents a92447a + 8684795 commit 431b6b5
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 4 deletions.
90 changes: 87 additions & 3 deletions src/Dapper.Oracle/OracleValueConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,87 @@ public static T Convert<T>(object value)
return default(T);
}

var valueType = value.GetType();
var nullableType = Nullable.GetUnderlyingType(typeof(T));

// 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)
{
var nullableType = Nullable.GetUnderlyingType(typeof(T));
return (T)System.Convert.ChangeType(value, nullableType ?? typeof(T));
}

// Convert the Oracle Array native data type to .NET Array data type.
// For example OracleString[] to string[] or
// For example OracleDecimal[] to decimal[] or
if (typeof(T).BaseType == typeof(Array) || valueType.BaseType == typeof(Array))
{
value = ConvertArray<T>(value);
return (T)System.Convert.ChangeType(value, nullableType ?? typeof(T));
}

return default(T);
}

/// <summary>
/// OracleString[] does not implement IConvertible therefore this is the only way to convert OracleString[] to string[] or OracleDecimal[] to .NET native data type
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <returns></returns>
private static T ConvertArray<T>(object value)
{
var nullableType = Nullable.GetUnderlyingType(typeof(T));
var arr = (Array)value;

switch (typeof(T).FullName)
{
case "Oracle.ManagedDataAccess.Types.OracleString[]":
return (T)System.Convert.ChangeType(value, nullableType ?? typeof(T));

case "System.Int16[]":
var shortArray = new short[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
shortArray[i] = short.Parse(arr.GetValue(i).ToString());
}
return (T)System.Convert.ChangeType(shortArray, nullableType ?? typeof(T));

case "System.Int32[]":
var intArray = new int[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
intArray[i] = int.Parse(arr.GetValue(i).ToString());
}
return (T)System.Convert.ChangeType(intArray, nullableType ?? typeof(T));

case "System.Int64[]":
var longArray = new long[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
longArray[i] = long.Parse(arr.GetValue(i).ToString());
}
return (T)System.Convert.ChangeType(longArray, nullableType ?? typeof(T));

case "System.Decimal[]":
case "Oracle.ManagedDataAccess.Types.OracleDecimal[]":
var decimalArray = new decimal[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
decimalArray[i] = decimal.Parse(arr.GetValue(i).ToString());
}
return (T)System.Convert.ChangeType(decimalArray, nullableType ?? typeof(T));

default:
var strArray = new string[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
strArray[i] = arr.GetValue(i).ToString();
}
return (T)System.Convert.ChangeType(strArray, nullableType ?? typeof(T));
}
}

/// <summary>
/// Gets the underlying primitive value from a nested type instance.
/// </summary>
Expand All @@ -60,14 +130,28 @@ private static object GetValue(object value)

if (IsOracleDataStructure(valueType))
{
var isNull = (bool)valueType.GetProperty("IsNull", typeof(bool))?.GetValue(value);
var isNullProp = valueType.GetProperty("IsNull", typeof(bool));
var isNull = false;

if (isNullProp != null)
{
var propValue = isNullProp?.GetValue(value);
if (propValue != null)
{
isNull = (bool)propValue;
}
}

if (isNull)
{
return null;
}

value = valueType.GetProperty("Value")?.GetValue(value);
var val = valueType.GetProperty("Value")?.GetValue(value);
if (val != null)
{
value = val;
}
}

return value;
Expand Down
39 changes: 38 additions & 1 deletion src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,43 @@ namespace Tests.Dapper.Oracle
{
public class OracleValueConverterTests
{
[Fact]
public void GetStringArray()
{
var oraArray = new[] { "Foo", "Bar" };
var result = OracleValueConverter.Convert<string[]>(oraArray);
result.Should().BeOfType<string[]>();
result.Should().HaveCount(2);
}

[Fact]
public void GetOracleStringArray()
{
var oraArray = new OracleString[] { "Foo", "Bar" };
var result = OracleValueConverter.Convert<OracleString[]>(oraArray);
result.Should().BeOfType<OracleString[]>();
result.Should().HaveCount(2);
}

[Fact]
public void GetOracleString2StringArray()
{
var oraArray = new OracleString[] { "Foo", "Bar" };
var result = OracleValueConverter.Convert<string[]>(oraArray);
result.Should().BeOfType<string[]>();
result.Should().HaveCount(2);
}

[Fact]
public void GetIntArray()
{
var oraArray = new OracleDecimal[] { 1, 2 };
var result = OracleValueConverter.Convert<int[]>(oraArray);
result.Should().BeOfType<int[]>();
result.Should().HaveCount(2);
}


[Fact]
public void GetOracleStringWithContentReturnsContent()
{
Expand Down Expand Up @@ -199,5 +236,5 @@ public void GetOracleDateTimeReturnsDateTime()
var result = OracleValueConverter.Convert<DateTime>(new OracleDate(DateTime.Today));
result.Should().Be(DateTime.Today);
}
}
}
}

0 comments on commit 431b6b5

Please sign in to comment.