diff --git a/build.ps1 b/build.ps1
index add4cf0..a013173 100644
--- a/build.ps1
+++ b/build.ps1
@@ -11,4 +11,4 @@ if ($connectionstring)
dotnet restore .\src\Dapper.Oracle.sln
dotnet build .\src\Dapper.Oracle.sln
dotnet test .\src\Dapper.Oracle.sln
-dotnet pack .\src\Dapper.Oracle.sln -p:PackageVersion=2.0.4
\ No newline at end of file
+dotnet pack .\src\Dapper.Oracle.sln -p:PackageVersion=2.1.0
diff --git a/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj b/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
index 3bdda7a..ee76527 100644
--- a/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
+++ b/src/Dapper.Oracle.StrongName/Dapper.Oracle.StrongName.csproj
@@ -1,9 +1,9 @@
-
+
false
- net7.0
+ net10.0
true
key.snk
@@ -13,10 +13,10 @@
-
+
-
+
-
\ No newline at end of file
+
diff --git a/src/Dapper.Oracle/Dapper.Oracle.csproj b/src/Dapper.Oracle/Dapper.Oracle.csproj
index 305e81d..0289057 100644
--- a/src/Dapper.Oracle/Dapper.Oracle.csproj
+++ b/src/Dapper.Oracle/Dapper.Oracle.csproj
@@ -1,26 +1,28 @@
-
+
false
- net7.0
+ net10.0
-Version 2.0.4:
- - Updated to use .net 7.0.
- - Dependency switched to most recent version of Dapper: 2.0.123.
- - Dependencies updated also for test project.
-
+ Version 2.1.0:
+ - Updated to use .net 10.0.
+ - Dependency switched to most recent version of Dapper: 2.1.72.
+ - Dependencies updated also for test project.
+ - Fix OracleDecimal to System.Decimal conversion overflow handling
+ - Enriching OracleParameterInfo with flag for PII data
+
-
+
-
+
-
\ No newline at end of file
+
diff --git a/src/Dapper.Oracle/OracleDecimalConversion.cs b/src/Dapper.Oracle/OracleDecimalConversion.cs
new file mode 100644
index 0000000..10c1226
--- /dev/null
+++ b/src/Dapper.Oracle/OracleDecimalConversion.cs
@@ -0,0 +1,17 @@
+namespace Dapper.Oracle
+{
+ ///
+ /// Maps Oracle native numeric values (especially OracleDecimal) to ,
+ /// using OracleDecimal.SetPrecision(..., 28) before reading System.Decimal (same idea as legacy ADO.NET).
+ ///
+ ///
+ /// Used internally by (for example from ).
+ /// Dapper's default Query<decimal> / ExecuteScalar<decimal> does not call this; for result sets use this helper on raw values, SQL CAST, or a custom TypeHandler.
+ ///
+ public static class OracleDecimalConversion
+ {
+ public static decimal ToDecimal(object value) => OracleValueConverter.Convert(value);
+
+ public static decimal? ToDecimalNullable(object value) => OracleValueConverter.Convert(value);
+ }
+}
diff --git a/src/Dapper.Oracle/OracleDynamicParameters.cs b/src/Dapper.Oracle/OracleDynamicParameters.cs
index cfb6bc5..10c7029 100644
--- a/src/Dapper.Oracle/OracleDynamicParameters.cs
+++ b/src/Dapper.Oracle/OracleDynamicParameters.cs
@@ -1,4 +1,4 @@
-//// Based on Gist found here: https://gist.github.com/vijaysg/3096151
+//// Based on Gist found here: https://gist.github.com/vijaysg/3096151
using System;
using System.Collections;
@@ -109,6 +109,7 @@ public void AddDynamicParams(dynamic param)
///
///
///
+ /// a flag that this param contains sensitive data and it must be masked in case of logging values
public void Add(
string name,
object value = null,
@@ -121,7 +122,8 @@ public void Add(
string sourceColumn = null,
DataRowVersion? sourceVersion = null,
OracleMappingCollectionType? collectionType = null,
- int[] arrayBindSize = null)
+ int[] arrayBindSize = null,
+ bool maskValueWhenLogging = false)
{
Parameters[Clean(name)] = new OracleParameterInfo()
{
@@ -136,7 +138,8 @@ public void Add(
SourceColumn = sourceColumn,
SourceVersion = sourceVersion ?? DataRowVersion.Current,
CollectionType = collectionType ?? OracleMappingCollectionType.None,
- ArrayBindSize = arrayBindSize
+ ArrayBindSize = arrayBindSize,
+ MaskValueWhenLogging = maskValueWhenLogging
};
}
@@ -167,7 +170,7 @@ public T Get(string name)
}
return default(T);
}
-
+
return OracleValueConverter.Convert(val);
}
@@ -239,10 +242,10 @@ protected virtual void AddParameters(IDbCommand command, SqlMapper.Identity iden
}
OracleMethodHelper.SetOracleParameters(p, param);
-
+
p.Direction = param.ParameterDirection;
-
- var val = param.Value;
+
+ var val = param.Value;
if (val != null && OracleTypeMapper.HasTypeHandler(val.GetType(), out var handler))
{
@@ -251,7 +254,7 @@ protected virtual void AddParameters(IDbCommand command, SqlMapper.Identity iden
else
{
p.Value = val ?? DBNull.Value;
-
+
var s = val as string;
if (s?.Length <= 4000)
{
@@ -262,8 +265,8 @@ protected virtual void AddParameters(IDbCommand command, SqlMapper.Identity iden
{
p.Size = param.Size.Value;
}
- }
-
+ }
+
if (add)
{
command.Parameters.Add(p);
@@ -320,6 +323,8 @@ public class OracleParameterInfo
public OracleParameterMappingStatus Status { get; set; }
public IDbDataParameter AttachedParam { get; set; }
+
+ public bool MaskValueWhenLogging { get; set; }
}
///
@@ -328,4 +333,4 @@ public class OracleParameterInfo
///
public IEnumerator GetEnumerator() => Parameters.GetEnumerator();
}
-}
\ No newline at end of file
+}
diff --git a/src/Dapper.Oracle/OracleValueConverter.cs b/src/Dapper.Oracle/OracleValueConverter.cs
index fe1f579..8aa9719 100644
--- a/src/Dapper.Oracle/OracleValueConverter.cs
+++ b/src/Dapper.Oracle/OracleValueConverter.cs
@@ -1,8 +1,9 @@
-using System;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data.Common;
using System.Linq;
+using System.Reflection;
using System.Reflection.Emit;
using System.Text.RegularExpressions;
@@ -126,7 +127,10 @@ private static T ConvertArray(object value)
var decimalArray = new decimal[arr.Length];
for (int i = 0; i < arr.Length; i++)
{
- decimalArray[i] = decimal.Parse(arr.GetValue(i)?.ToString());
+ var raw = arr.GetValue(i);
+ decimalArray[i] = TryReduceOracleDecimalToSystemDecimal(raw, out var systemDecimal)
+ ? systemDecimal
+ : decimal.Parse(raw?.ToString() ?? "0");
}
return (T)System.Convert.ChangeType(decimalArray, nullableType ?? typeof(T));
case "System.Boolean[]":
@@ -187,6 +191,12 @@ private static object GetValue(object value)
return null;
}
+ // Legacy ADO.NET: OracleDecimal.SetPrecision(..., 28).Value — no compile-time reference to Oracle.ManagedDataAccess.
+ if (TryReduceOracleDecimalToSystemDecimal(value, out var asDecimal))
+ {
+ return asDecimal;
+ }
+
var val = valueType.GetProperty("Value")?.GetValue(value);
if (val != null)
{
@@ -208,5 +218,45 @@ private static bool IsOracleDataStructure(Type valueType)
// 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+");
}
+
+ private const string OracleDecimalTypeFullName = "Oracle.ManagedDataAccess.Types.OracleDecimal";
+
+ private static bool IsOracleDecimal(Type type) =>
+ type != null && type.FullName == OracleDecimalTypeFullName;
+
+ ///
+ /// Calls OracleDecimal.SetPrecision(instance, 28).Value via reflection when ODP.NET is loaded at runtime.
+ ///
+ private static bool TryReduceOracleDecimalToSystemDecimal(object value, out decimal systemDecimal)
+ {
+ systemDecimal = default;
+ if (value == null || !IsOracleDecimal(value.GetType()))
+ {
+ return false;
+ }
+
+ var t = value.GetType();
+ var setPrecision = t.GetMethod(
+ "SetPrecision",
+ BindingFlags.Public | BindingFlags.Static,
+ binder: null,
+ types: new[] { t, typeof(int) },
+ modifiers: null);
+ if (setPrecision == null)
+ {
+ return false;
+ }
+
+ var reduced = setPrecision.Invoke(null, new object[] { value, 28 });
+ var valueProp = t.GetProperty("Value");
+ var boxed = valueProp?.GetValue(reduced);
+ if (boxed is decimal d)
+ {
+ systemDecimal = d;
+ return true;
+ }
+
+ return false;
+ }
}
}
diff --git a/src/Tests.Dapper.Oracle/IntegrationTests/DatabaseFixture.cs b/src/Tests.Dapper.Oracle/IntegrationTests/DatabaseFixture.cs
index 80c64c6..f3477ce 100644
--- a/src/Tests.Dapper.Oracle/IntegrationTests/DatabaseFixture.cs
+++ b/src/Tests.Dapper.Oracle/IntegrationTests/DatabaseFixture.cs
@@ -35,10 +35,9 @@ public void Dispose()
public async Task InitializeAsync()
{
+ // Prefer DA_OR_CONNECTION (CI / local Oracle). Do not overwrite it — a hardcoded default used to break env-based runs.
var connectionString = Environment.GetEnvironmentVariable("DA_OR_CONNECTION");
- connectionString = "Data Source=localhost/dips;User Id=system;Password=oracle";
-
if (string.IsNullOrEmpty(connectionString))
{
var si = new ProcessStartInfo("powershell", @".\LocalOracleDockerDb.ps1");
@@ -100,4 +99,4 @@ private static string GetBootstrapFolder()
}
}
-}
\ No newline at end of file
+}
diff --git a/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs b/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
index dcc0ef5..b3ba639 100644
--- a/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
+++ b/src/Tests.Dapper.Oracle/OracleValueConverterTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Text;
using Dapper.Oracle;
using FluentAssertions;
@@ -249,6 +249,22 @@ public void GetOracleDecimalReturnsDecimal()
result.Should().Be(expected);
}
+ [Fact]
+ public void GetOracleDecimalMatchesExplicitSetPrecision28()
+ {
+ foreach (var d in new[]
+ {
+ 0m,
+ 1m,
+ 0.4690679611650485436893203883m,
+ })
+ {
+ var od = new OracleDecimal(d);
+ var expected = OracleDecimal.SetPrecision(od, 28).Value;
+ OracleValueConverter.Convert(od).Should().Be(expected);
+ }
+ }
+
[Fact]
public void GetOracleDecimalReturnsNullableDecimal()
{
diff --git a/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj b/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
index af10b18..bf51727 100644
--- a/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
+++ b/src/Tests.Dapper.Oracle/Tests.Dapper.Oracle.csproj
@@ -1,22 +1,27 @@
-
+
true
- net7.0
+ net10.0
false
+
+ false
+
+
+ Category!=Integration&Category!=IntegrationTest
-
-
-
-
-
+
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
@@ -36,7 +41,7 @@
-
+
-
\ No newline at end of file
+