C# 将SqlDecimal转换为Decimal时发生OverflowException
在我们的实际应用程序中,当试图将99的值转换为System.Decimal时,会出现OverflowException。引发异常是因为SqlDecimal的精度高于System.Decimal的精度 以下是重现问题的测试:C# 将SqlDecimal转换为Decimal时发生OverflowException,c#,.net,sql-server,exception,decimal,C#,.net,Sql Server,Exception,Decimal,在我们的实际应用程序中,当试图将99的值转换为System.Decimal时,会出现OverflowException。引发异常是因为SqlDecimal的精度高于System.Decimal的精度 以下是重现问题的测试: [Test] public void SqlDecimalToDecimalOverflowTest() { // in our real application d1 & d2 are loaded from a database; both are dec
[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的最快方法是什么? 不久前,我写了这个helper方法:
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-29位的System.Decimal是不够的).在除法操作后,应恢复
d3
中精度和比例属性的值:
var d3 = d1.Value / d2;
d3 = SqlDecimal.ConvertToPrecScale(d3, 28, 5);
谢谢你,鲁斯塔姆。在我们的例子中,是的,我们可以使用ConvertToPrecScale()并指定正确的精度和比例,因为我们在生成的数据模型的属性中有这些信息。但是,如果我想要一个通用的解决方案,却不知道它的精度和规模呢?我的意思是,如果我只是想从数字中删除额外/不必要的比例(就像我的RecreateWithMinPrecScale()方法所做的那样),该怎么办?