I know there are several threads and posts regarding this issue in the internet and I've read them (not every article, I have to admit) but none of them did fully satisfy me.
My situation:
I'm using ODP.net (dll version 2.111.6.0) to access the Oracle DB (version 10 + 11) and a DataReader to retrieve the data (.NET 3.5, C#).
Using this code results in a 'System.OverflowException (Arithmetic operation resulted in an overflow.)'
decimal.TryParse(oraReader.GetOracleDecimal(0).Value.ToString(),
NumberStyles.Any, null, out parsedOraDecimal)
and this one results in a value of '3,000000000000000000000000000000000000000000000000000000000E-126'
decimal.TryParse(oraReader.GetOracleValue(0).ToString(),
NumberStyles.Any, null, out parsedOraDecimal)
Now I have to find some way to retrieve and evaluate this value properly - the DB is also used from other apps which are out of my control so changes there are not possible.
Converting the types in my C# code from 'decimal' to 'double' is also not really an option.
Any ideas?
The Oracle NUMBER data type is used to store numeric values that can be negative or positive. The following illustrates the syntax of the NUMBER data type: NUMBER[(precision [, scale])] The Oracle NUMBER data type has precision and scale. The precision is the number of digits in a number.
TO_NUMBER converts expr to a value of NUMBER datatype. The expr can be a BINARY_FLOAT or BINARY_DOUBLE value or a value of CHAR , VARCHAR2 , NCHAR , or NVARCHAR2 datatype containing a number in the format specified by the optional format model fmt .
Each value is stored in scientific notation, with 1 byte used to store the exponent. The database uses up to 20 bytes to store the mantissa, which is the part of a floating-point number that contains its significant digits. Oracle Database does not store leading and trailing zeros.
OracleDecimal has a larger precision than decimal. For that reason, you have to reduce the precision first. Forget all the parsing, use implicit conversion. Try something along the lines of (untested):
decimal d = (decimal)(OracleDecimal.SetPrecision(oraReader.GetOracleDecimal(0), 28));
I just had a similar issue, and tried the approach of changing the OracleDataAdapter to return Oracle specific types ( data_adapter.ReturnProviderSpecificTypes = true; ), but this is just a PITA, you end up casting OracleStrings back to strings, etc.
In the end I solved it by doing the precision rounding in the SQL statement using Oracle's round function:
SELECT round( myfield, 18 ) FROM mytable
Dotnet will then happily convert the figure to a decimal.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With