Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

No way to store big numbers with a lot of decimal spaces (without storing it in the database as text) #1907

Closed
Templayer opened this issue Jun 1, 2023 · 15 comments · Fixed by #1910

Comments

@Templayer
Copy link

Templayer commented Jun 1, 2023

We have MSSQL databases that have a column typed as numeric(30,15).

The database works with a Java application (which has the column used as BigDecimal in its entity).

Now I'm trying to make a C# microservice that puts a number into the same column, but I'm striking some limits here.

The numeric type in C# has a precision of only 29 and we have 30, which means that numeric cannot be used and .NET / C# doesn't have an equivalent to Java's BigDecimal yet.

So far I have tried the ExtendedNumerics.BigDecimal NuGet package, but that doesn't work with Dapper.

Trying to insert it as a string gives me:

Arithmetic overflow error converting nvarchar to data type numeric.
      The statement has been terminated.

How to test: Try storing 999999999999999.999999999999999 into an MSSQL numeric(30,15) column. Works in Java with Hibernate, can't do it in C# with Dapper. :'(

Why such big numbers? Chemical measurements.

The kitty is sad. And tired.

@mgravell
Copy link
Member

mgravell commented Jun 1, 2023

Before we can even talk about it in terms of Dapper: does it work in ADO.NET / SqlClient?

@Templayer
Copy link
Author

Templayer commented Jun 2, 2023

Before we can even talk about it in terms of Dapper: does it work in ADO.NET / SqlClient?

I don't know, probably not.

SqlClient gave me a lot of problems. Dapper doesn't install it via NuGet by default, and it gave me the dreaded platform not supported exception, which I found out after hours of googling is because it doesn't detect pretty much half Linux distributions as Linux, which included Linux Mint. This means it took me the better part of the day getting Dapper working because of this dependency alone. And I had to make a horrible hack to get SqlClient working.

Anyway, the question stands - how do I put "big enough" numbers into an MSSQL numeric(30,15) column via Dapper?

EDIT: the SqlClient errors have Dapper in the stacktrace, so at least I know Dapper got used.

@mgravell
Copy link
Member

mgravell commented Jun 2, 2023

Dapper sits on top of ADO.NET, with SqlClient being the MSSQL ADO.NET provider; if it isn't possible with ADO.NET/SqlClient, it cannot be possible with Dapper. Hence the importance of my question.

@Templayer
Copy link
Author

Dapper sits on top of ADO.NET, with SqlClient being the MSSQL ADO.NET provider; if it isn't possible with ADO.NET/SqlClient, it cannot be possible with Dapper. Hence the importance of my question.

https://stackoverflow.com/questions/14402211/net-sql-server-nhibernate-and-high-precision-decimals

@mgravell
Copy link
Member

mgravell commented Jun 2, 2023

That's very useful, thanks; so what this really becomes, then, is:

can dapper directly support SqlDecimal?

is that right? meaning: if you provided data in terms of SqlDecimal rather than (say) decimal or string, and had a SqlDecimal that happened to have the value (i.e. SqlDecimal.Parse("999999999999999.999999999999999")) - and similarly read: is that sufficient?

@Templayer
Copy link
Author

That's very useful, thanks; so what this really becomes, then, is:

can dapper directly support SqlDecimal?

is that right? meaning: if you provided data in terms of SqlDecimal rather than (say) decimal or string, and had a SqlDecimal that happened to have the value (i.e. SqlDecimal.Parse("999999999999999.999999999999999")) - and similarly read: is that sufficient?

I guess? I'm not at work anymore, so I cannot test what will I get with SqlDecimal.Parse("999999999999999.999999999999999"), but there simply needs to be SOME way to get it inside that damn column. :D

@mgravell
Copy link
Member

mgravell commented Jun 2, 2023

You'll get a SqlDecimal value that retains the full scale and precision value that we are discussing :) sounds like this is what we need to get working

@Templayer
Copy link
Author

You'll get a SqlDecimal value that retains the full scale and precision value that we are discussing :) sounds like this is what we need to get working

Yup.

@Templayer
Copy link
Author

Templayer commented Jun 8, 2023

Any news? Currently, I'm working around this by catching an exception from converting a string to Decimal and then trying to parse it again, but this time with the last decimal number removed from the string.

That's hardly ideal. In corporate code, nonetheless. :D

@mgravell
Copy link
Member

mgravell commented Jun 9, 2023

so... PR in progress; thanks for providing epic evidence of what I was saying in #1909, because wow that was harder than it should have been

@Templayer
Copy link
Author

so... PR in progress; thanks for providing epic evidence of what I was saying in #1909, because wow that was harder than it should have been

I've read through the linked Issues just to understand what you are saying and my response is: "Yaay!"

Please notify me when there is a NuGet available with those changes.

The microservice might be (maybe) deployed into production next week for a first set of trial runs.

I don't know how long my workaround of clipping away the last decimal number (to fit it into Decimal) is going to last. 👀

But hey, if deployed into production, you will be able to boast that Dapper is running on a Slovak Nuclear Powerplant. :P :D :D

And that is pretty much the limit of what I can say while not breaking the non-disclosure agreement.

@mgravell
Copy link
Member

mgravell commented Jun 9, 2023

<PackageReference Include="Dapper" Version="2.0.138" />

This is not currently "listed", but: it exists

@mgravell
Copy link
Member

mgravell commented Jun 9, 2023

Oh, I should have said explicitly: you need to use SqlDecimal for this to work; decimal simply can't hold your value. I have tested (on both System.Data.SqlClient and Microsoft.Data.SqlClient):

  • Query[etc]<SqlDecimal>(...)
  • Query[etc]<SqlDecimal?>(...)
  • Query[etc]<SomeTypeThatHasSqlDecimalMember>
  • Query[etc]<SomeTypeThatHasNullableSqlDecimalMember>
  • Query[etc]<(...value tuple using SqlDecimal...)>
  • Query[etc]<(...value tuple using SqlDecimal?...)>
  • execute/query using SqlDecimal as a member on a parameter object
  • execute/query using SqlDecimal? as a member on a parameter object
  • (note that ExecuteScalar does not work returning SqlDecimal, due to the providers themselves; this is beyond Dapper's control)

if you find some obscure scenario that I've missed: please let me know!

@Templayer
Copy link
Author

Going to test it out on Monday. Work work work!

"execute/query using SqlDecimal as a member on a parameter object" should be my scenario. I just need to get it into the database somehow. :^)

@Templayer
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants