question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Numeric value does not fit in a System.Decimal (value less than decimal.MaxValue)

See original GitHub issue

I first looked at posts with a similar issues, for example

https://github.com/npgsql/efcore.pg/issues/438 https://github.com/npgsql/npgsql/issues/3238 https://github.com/npgsql/npgsql/issues/448

and didn’t find a solution to my issue

Introductory information

There are many type fields in our database: numeric (56,28) and numeric (55,19), everything worked fine in Npgsql 3.7 But when we updated the Npgsql version to 4.0/4.1/5 then some!!! fields have ceased to be correctly retrieved from the database below is an example of such a value

Steps to reproduce

for example:

  1. database field: numeric (55,19)
  2. save the value in the field: 99999999999
  3. if we make a select from this field, we get: 99999999999.0000000000000000000

simple code for reproduce:

using (var dbConn = new NpgsqlConnection("..."))
{
	dbConn.Open();
	var cmd = new NpgsqlCommand("select 99999999999.0000000000000000000::numeric", dbConn);
	var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess);
	reader.Read();
	reader.GetValue(0);
}

The issue

We get an exception in any Npgsql above version 3.7 In Npgsql version 3.7 everything works fine

Exception message: System.OverflowException: 'Numeric value does not fit in a System.Decimal'
Stack trace:
Stack trace: 
This exception was originally thrown at this call stack:
    Npgsql.Internal.TypeHandlers.NumericHandlers.DecimalRaw.Multiply(ref Npgsql.Internal.TypeHandlers.NumericHandlers.DecimalRaw, uint) in DecimalRaw.cs
    Npgsql.Internal.TypeHandlers.NumericHandlers.NumericHandler.Read(Npgsql.Internal.NpgsqlReadBuffer, int, Npgsql.BackendMessages.FieldDescription) in NumericHandler.cs
    Npgsql.Internal.TypeHandling.NpgsqlSimpleTypeHandler<TDefault>.Read<TAny>(Npgsql.Internal.NpgsqlReadBuffer, int, Npgsql.BackendMessages.FieldDescription) in NpgsqlSimpleTypeHandler.cs
    Npgsql.Internal.TypeHandling.NpgsqlSimpleTypeHandler<TDefault>.Read<TAny>(Npgsql.Internal.NpgsqlReadBuffer, int, bool, Npgsql.BackendMessages.FieldDescription) in NpgsqlSimpleTypeHandler.cs
    [External Code]
    Npgsql.Internal.TypeHandling.NpgsqlTypeHandler<TDefault>.ReadAsObject(Npgsql.Internal.NpgsqlReadBuffer, int, bool, Npgsql.BackendMessages.FieldDescription) in NpgsqlTypeHandler`.cs
    [External Code]
    Npgsql.NpgsqlDataReader.GetValue(int) in NpgsqlDataReader.cs
    ConsoleApp1.Program.Main(string[]) in Program.cs

Further technical details

Npgsql version: Npgsql 4.0/4.1/5.0 PostgreSQL version: PostgreSQL 10.8 Operating system: Windows 10

https://github.com/npgsql/npgsql/blob/v4.1.4/src/Npgsql/TypeHandlers/NumericHandlers/DecimalRaw.cs Screenshot with error: error

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:8 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
rojicommented, Apr 3, 2021

Thanks @YohDeadfall!

0reactions
YohDeadfallcommented, Apr 5, 2021

@SomeSpy, you have to change the following method:

https://github.com/npgsql/npgsql/blob/0f80008ce02415553a0a9b82f449afb45a04acb6/src/Npgsql/Internal/TypeHandlers/NumericHandlers/NumericHandler.cs#L42-L104

As you can see it throws on an overflow, but should not in your case. Therefore, tweak the logic in a such way that reading fractional part after reaching the maximum capacity of decimal will just take the first overflowing group, check that the digit at the overflowing position is less or equal to 5 and add 1 to the result in that case. Otherwise, do nothing. Read left groups till the end, but discard values.

You should find in other threads how PostgreSQL stores and handles numerics, but to be short, they are stored in groups of 4 decimal digits. Each group is multiplied by 10^(4 * g) where g is the number of groups minus the current group index. So 1234567 can be represented as 0123 and 4567. The scale complicates the logic a bit, but no so much.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Numeric value does not fit in a System.Decimal
Now when I select that column, using below query, it returns the value that will properly fits in decimal data type of c#,...
Read more >
Numeric value does not fit in a System.Decimal
Hi EasyMorph Team, I am using the PostGreSQL connector and I am trying to retrieve a column that is defined as “numeric(50,30)” and...
Read more >
Decimal Struct (System)
Clamps a value to an inclusive minimum and maximum value. Compares two specified Decimal values.
Read more >
System.Decimal Structure
The Decimal type can represent values with at least 28 significant digits. ... value is one of the following: greater than System.Decimal.MaxValue. less...
Read more >
What is Decimal.MaxValue in C#?
MaxValue is a decimal field that represents the largest possible value of a decimal. It is constant and read-only, meaning that it cannot...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found