在我们的实际应用程序中,我们在尝试将SqlDecimal值99转换为System.Decimal时遇到OverflowException。抛出异常是因为SqlDecimal的精度高于System.Decimal的精度。
这是一个重现问题的测试:
[Test]
public void SqlDecimalToDecimalOverflowTest()
{
// in our real application d1 & d2 are loaded from a database; both are declared as DECIMAL(28, 5)
// for test purposes I recreate identical SqlDecimal objects here:
var d1 = new SqlDecimal(28, 5, true, 9900000, 0, 0, 0); // Debugger shows {99.00000}
var d2 = new SqlDecimal(28, 5, true, 100000, 0, 0, 0); // Debugger shows {1.00000}
var d3 = d1.Value / d2; // Debugger shows d1.Value as {99}, d1.Value is of type decimal (not SqlDecimal)
var exception = d3.Value; // Debugger shows d3 as {99.0000000000000000000000000000000}
}
截图:
问题是:
将此类SqlDecimal对象转换为Decimal的最快方法是什么?
前段时间我写过这个辅助方法:
public static SqlDecimal RecreateWithMinPrecScale(this SqlDecimal value)
{
string s = value.Scale > 0 ? value.ToString().TrimEnd('0') : value.ToString();
int delimiterIndex = s.IndexOf(".");
int precision = s.Length - (delimiterIndex >= 0 ? 1 : 0) - (s.StartsWith("-") ? 1 : 0);
int scale = delimiterIndex >= 0 ? s.Length - 1 - delimiterIndex : 0;
return SqlDecimal.ConvertToPrecScale(value, precision, scale);
}
所以我可以写
var ok = d3.RecreateWithMinPrecScale().Value; // no exception
但显然这是一种缓慢而低效的方法,我们需要进行数十亿次此类计算。
请让我们不讨论为什么我们使用SqlDecimal类而不仅仅是System.Decimal(它是一个金融应用程序,我相信以前我们有要求支持很长的数字(大或精))据说System.Decimal的28-29位数字可能不够。)
答案 0 :(得分:2)
您应该在除法运算后恢复d3
中精度和比例属性的值:
var d3 = d1.Value / d2;
d3 = SqlDecimal.ConvertToPrecScale(d3, 28, 5);