SqlClient: SqlClient fails to convert decimal(38,20) to .Net decimal for values within the range of .Net's decimal type
This program
static void Main(string[] args)
{
using (var con = new SqlConnection("server=.;database=tempdb;Integrated Security=true"))
{
con.Open();
var cmd = new SqlCommand("select cast(4210862852.86 as decimal(38,20)) val", con);
using (SqlDataReader rdr = cmd.ExecuteReader())
{
rdr.Read();
var val = rdr.GetDecimal(0);
Console.WriteLine(val);
}
}
}
fails with
System.OverflowException: ‘Conversion overflows.’
at SqlBuffer.cs line 254:
if (StorageType.Decimal == _type)
{
if (_value._numericInfo.data4 != 0 || _value._numericInfo.scale > 28)
{
throw new OverflowException(SQLResource.ConversionOverflowMessage);
}
This value is well within the range of a .NET decimal, and it’s a value that the SqlClient can write using a SqlParameter. So it should be converted to .NET decimal.
The byte pattern in SQL and TDS for this value is:
0x261400010000D877FB4DEE8B51699A5005000000
And it looks like SqlBuffer refuses to convert any value with a non-zero value in the last 4 bytes. But a .NET Decimal is stored as a 12-byte integer, along with a sign and a scaling factor.
So the apparent intent is to determine if the SqlDecimal uses a larger-than-12 byte integer and trigger the overflow.
So this conversion has a bug. It looks like the SqlClient is confused on the byte ordering SQL Server is using, and the last 4 bytes of this buffer are not the 4 least-significant bytes of the 16-byte integer embedded in the decimal.
This number requires uses 12 (base-10) decimal digits to store, so it requires fewer than 12 (base-256) bytes to store.
https://docs.microsoft.com/en-us/dotnet/api/system.decimal?redirectedfrom=MSDN&view=netframework-4.8
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 5
- Comments: 15 (5 by maintainers)
Commits related to this issue
- Fix for decimal conversion overflow bug When mapping data from SQL Decimal(38,15) to .net decimal, this driver is throwing Conversion Overflow exception. Bug is already tracked under https://github.c... — committed to pashokchakravarthi/SqlClient by pashokchakravarthi 4 years ago
- Fix for decimal conversion overflow bug When mapping data from sql Decimal(38,15) to .net decimal, this driver is throwing CoNversion overflow exception. Bug is already tracked under https://github.c... — committed to pashokchakravarthi/SqlClient by pashokchakravarthi 4 years ago
It is on the to-do list this semester.