【发布时间】:2016-09-23 19:20:18
【问题描述】:
在我们的实际应用程序中,当尝试将 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(它是一个金融应用程序,我相信以前我们需要支持非常长的数字(无论是大的还是精确的),据说 28- System.Decimal 29 位可能不够)。
【问题讨论】:
标签: c# .net sql-server exception decimal