Это ошибка или ограничение в .NET SqlClient. Вот репродукция:
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);
}
}
Проблема в том, что это число
select cast(cast(4210862852.86 as decimal(38,20)) as varbinary(20))
сохраняется и передается по проводам как
0x261400010000D877FB4DEE8B51699A5005000000
И SqlClient откажется преобразовывать любое десятичное число с ненулевым значением в последних 4 байтах:
internal decimal Decimal
{
get
{
ThrowIfNull();
if (StorageType.Decimal == _type)
{
if (_value._numericInfo.data4 != 0 || _value._numericInfo.scale > 28)
{
throw new OverflowException(SQLResource.ConversionOverflowMessage);
}
return new decimal(_value._numericInfo.data1, _value._numericInfo.data2, _value._numericInfo.data3, !_value._numericInfo.positive, _value._numericInfo.scale);
}
if (StorageType.Money == _type)
{
long l = _value._int64;
bool isNegative = false;
if (l < 0)
{
isNegative = true;
l = -l;
}
return new decimal((int)(l & 0xffffffff), (int)(l >> 32), 0, isNegative, 4);
}
return (decimal)this.Value; // anything else we haven't thought of goes through boxing.
}
}
https://github.com/dotnet/corefx/blob/master/src/System.Data.SqlClient/src/System/Data/SqlClient/SqlBuffer.cs
Я открыл проблему с .NET Core здесь: https://github.com/dotnet/corefx/issues/37592