测试SqlDecimal和C#Decimal

时间:2016-11-30 19:57:05

标签: c# sql-server type-conversion decimal

我正在尝试验证c#中的小数是否适合db列十进制。 SqlDecimal对象允许您将精度和小数位以及小数位传递给构造函数。我知道列的大小,所以在我们编写数据之前,我检查每个输入,这样我就可以生成业务所需的输出。

在这种情况下,我们存储百分比,因此精度 13 且比例 10 。我有一个测试工具,我已经在下面浓缩成了针对SO的unti测试。此示例在SqlDecimal构造函数行上抛出了算术溢出错误:

    [TestMethod]
    public void TestDecimalFits()
    {
        decimal d = 10.3m;
        SqlDecimal sqlDecimal = new SqlDecimal(13, 10, d >= 0, Decimal.GetBits(d));
        Assert.AreEqual(d, sqlDecimal.Value);
    }

有谁知道为什么会爆炸?

谢谢!

2 个答案:

答案 0 :(得分:1)

Decimal.GetBits的返回与SqlDecimal的构造函数参数不兼容。

Decimal.GetBits返回一个数组,表示十进制的确切结构,包括96位缩放的整数值和指数的8位(加1个符号位和27个未使用的位)。

您正在使用的SqlDecimal constructor采用int数组表示" 128位无符号整数,它提供新SqlDecimal的值。" - 不是该十进制值的代表scale参数确定小数的实际值是什么。

因此,您实际上传递的值不同于构造函数所期望的值。 .NET十进制等效值10.3m是

0000000001100111-0000000000000000-0000000000000000-10000000000000000

其中1100111是二进制等效值103,而1是比例。

该二进制值的等价整数大于13位,这就是为什么在将它传递给SqlDecimal构造函数时会出现溢出的原因。

我不会玩bit-fiddling而只是使用原始decimal值,让SQL将其转换为正确的精度并自动缩放。

  

我试图验证c#中的小数是否适合db列十进制。

嗯,适合DECIMAL(13,10)的最大值是999.9999999999,远远低于decimal的最大值。所以不,你不能在DECIMAL(13,10) SQL列中存储任何 C#十进制值。

(从技术上讲,我认为您可以通过降低精度来存储9999999999999,但即使这样也远低于decimal的最大值。

答案 1 :(得分:0)

我的猜测是Decimal.GetBits(d)溢出了Int32返回类型。 尝试只做Int32 bits = Decimal.GetBits(d)并查看它是否会抛出相同的错误。