我似乎无法在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#?
答案 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