从OracleDataAdapter.Fill()填充DataTable时“指定的强制转换无效”

时间:2014-05-29 14:24:49

标签: c# oracle casting datatable decimal

我似乎无法在Google(或StackOverflow)的任何地方找到这个问题,这让我感到很惊讶,所以我会把它放在这里以帮助处于相同情况的其他人。

我有一个在Oracle Sql Developer上运行良好的SQL查询,但当我使用C#通过adapter.Fill(table)运行它以获得结果时,我得到Specified cast is not valid个错误({{1 }})。

以下是C#代码的简化版本:

System.InvalidCastException

这是SQL的简化版本:

var resultsTable = new DataTable();

using (var adapter = new OracleDataAdapter(cmd))
{
    var rows = adapter.Fill(resultsTable);  // exception thrown here, but sql runs fine on Sql Dev

    return resultsTable;
}

如果我删除了除法条款,它就不会出错 - 所以它是特定的。但是,market_value和SELECT acct_no, market_value/mv_total FROM myTable WHERE NVL(market_value, 0) != 0 AND NVL(mv_total, 0) != 0 都是Number(19,4)类型,我可以看到Oracle适配器期望小数,所以正在进行什么演员?为什么它适用于SqlDev但不适用于C#?

3 个答案:

答案 0 :(得分:35)

回答我自己的问题:

因此,似乎Oracle数字类型可以包含比C#十进制类型更多的小数位,并且如果Oracle尝试返回的内容超过C#可以保留,则会抛出InvalidCastException。

解?

在你的sql中,将任何可能包含太多小数位的结果舍入到合理的位置。所以我这样做了:

SELECT acct_no, ROUND(market_value/mv_total, 8)  -- rounding this division solves the problem
FROM myTable
WHERE NVL(market_value, 0) != 0
AND NVL(mv_total, 0) != 0

它有效。

带走的是:Oracle数字类型与C#decimal之间不兼容。限制Oracle小数位以避免无效的强制转换异常。

希望这有助于其他人!

答案 1 :(得分:5)

我知道这个帖子真的很老..但是我遇到了类似的问题。

我必须在Oracle Decimal列上使用Oracle方法TO_BINARY_DOUBLE

的最佳解决方案

答案 2 :(得分:0)

我知道已经回答了这个问题,但是我也找到了我也使用的另一种选择。我在现场遇到麻烦的时候使用了CAST。

基于OP的SELECT命令:

SELECT acct_no, CAST((market_value/mv_total) AS DECIMAL(14,4))  -- CAST to decimal here
FROM myTable
WHERE NVL(market_value, 0) != 0
AND NVL(mv_total, 0) != 0