首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SqlDataAdapter.Fill() OverflowException

SqlDataAdapter.Fill() OverflowException
EN

Stack Overflow用户
提问于 2014-04-25 11:08:48
回答 1查看 2K关注 0票数 1

我需要从DB获取数据并执行以下代码:

代码语言:javascript
复制
using (var dataRetrievingCommand = new SqlCommand(selectQuery, connection))
{
    var dataTable = new DataTable("DataTable");
    var sda = new SqlDataAdapter(dataRetrievingCommand);
    sda.Fill(dataTable); //OverflowException here
    return dataTable;
}

问题是数据库中的某些列具有decimal(38,10)decimal(38, 0)等类型,它们的值范围大于C#中的decimal类型,这就是为什么我得到了OverflowException

有没有办法在不修改C#查询和数据库结构的情况下选择C#中的数据?

如果DB值精度高于C#,则可以舍入该值。如果发生溢出,我希望看到NULL,否则任何其他标记都无法读取。

调查详情:

这个问题听起来很受欢迎,但我发现只有微软论坛上的一根线有同样的问题,没有答案。

2008本身无法在编辑数据模式下显示这些值--它显示"“,并且不允许编辑这些单元格。

但SELECT、INSERT和UPDATE命令工作正常,并显示所有数据。

精度为28或更低的十进制可以正常工作,但是任何高精度的列都会失败,即使值不会导致像十进制(38,38)那样的溢出,可以像nvarchar那样在insert上进行微调。

代码语言:javascript
复制
sda.ContinueUpdateOnError = true;

什么都改变不了。我认为这不是一个更新操作,所以这个属性被忽略了。

代码语言:javascript
复制
sda.FillError += (sender, args) =>
{
    args.Continue = true;
};

停止异常抛出,但根本不返回任何数据--只有一个无意义的行。

代码语言:javascript
复制
 CaseName | Decimal_10_2 | Decimal_18_0 | Decimal_18_18 | Decimal_28_0 | Decimal_28_28 | Decimal_38_0 | Decimal_38_20 | Decimal_38_38 | Float | Int
----------+--------------+--------------+---------------+--------------+---------------+--------------+---------------+---------------+-------+----
 Null     |              |              |               |              |               |              |               |               |       |    
EN

回答 1

Stack Overflow用户

发布于 2014-04-25 12:27:56

看来我自己找到了解决办法。

代码语言:javascript
复制
sda.ReturnProviderSpecificTypes = true;

之后,DataTable单元格包含System.Data.SqlTypes.SqlDecimalSystem.Data.SqlTypes.SqlString等类型的值,这些值可以通过自定义错误处理进一步转换为原生.NET数据类型。

然后检查PrecisionScale值的属性,如果需要,使用SqlDecimal.AdjustScale()方法对值进行舍入。可以通过Value属性访问结果。见我的执行情况:

代码语言:javascript
复制
public struct DecimalEx
{
    private decimal m_Value;

    public decimal Value
    {
        get { return m_Value; }
    }

    private bool m_IsNull;

    public bool IsNull
    {
        get { return m_IsNull; }
    }

    private bool m_IsOverflow;

    public bool IsOverflow
    {
        get { return m_IsOverflow; }
    }

    private bool m_IsRounded;

    public bool IsRounded
    {
        get { return m_IsRounded; }
    }

    private bool m_IsPositive;

    public bool IsPositive
    {
        get { return m_IsPositive; }
    }

    public DecimalEx(decimal value)
    {
        m_Value = value;
        m_IsNull = false;
        m_IsOverflow = false;
        m_IsRounded = false;
        m_IsPositive = value >= 0;
    }

    public static explicit operator DecimalEx(SqlDecimal dbValue)
    {
        var result = new DecimalEx();
        if (dbValue.IsNull)
        {
            result.m_Value = 0;
            result.m_IsNull = true;
            result.m_IsOverflow = false;
            result.m_IsRounded = false;
            result.m_IsPositive = false;
            return result;
        }
        else
        {
            result.m_IsNull = false;
            result.m_IsPositive = dbValue.IsPositive;
        }

        if (dbValue.Precision > 28)
        {
            result.m_IsRounded = true;

            if (dbValue.Precision - dbValue.Scale <= 28)
            {
                var adjustedValue = SqlDecimal.AdjustScale(dbValue, 28 - dbValue.Precision, true);
                result.m_Value = adjustedValue.Value;
                result.m_IsOverflow = false;
            }
            else
            {
                result.m_Value = 0;
                result.m_IsOverflow = true;
            }
        }
        else
        {
            result.m_Value = dbValue.Value;
            result.m_IsRounded = false;
        }

        return result;
    }

    public override string ToString()
    {
        return ToString(CultureInfo.CurrentCulture);
    }

    public string ToString(IFormatProvider provider)
    {
        if (IsNull)
        {
            return string.Empty;
        }
        if (IsOverflow)
        {
            return "###";
        }
        return Value.ToString(provider);
    }
}

更新:对AdjustScale方法要小心,因为它的文档不准确-- digits参数不是结果值中的位数,而是数字数的变化(因此,要将精度降低2,必须通过digits=-2)

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23291328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档