指定的格式无效"当从OracleDataAdapter.Fill()填充数据表时
本文关键字:Fill OracleDataAdapter 填充 数据表 当从 格式 无效 quot | 更新日期: 2023-09-27 18:05:40
我似乎在Google(或StackOverflow)上找不到这个问题,这真的让我很惊讶,所以我把它放在这里帮助那些有同样情况的人。
我有一个SQL查询在Oracle SQL Developer上运行良好,但是当我使用adapter.Fill(table)
通过C#
运行它来获得结果时,我得到Specified cast is not valid
错误(System.InvalidCastException
)。
下面是c#代码的精简版本:
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;
}
下面是SQL的简化版本:
SELECT acct_no, market_value/mv_total
FROM myTable
WHERE NVL(market_value, 0) != 0
AND NVL(mv_total, 0) != 0
如果我删除除法子句,它不会出错-所以它是特定于此的。但是,market_value和mv_total
的类型都是Number(19,4),并且我可以看到Oracle适配器期待一个小数,那么发生了什么类型的转换呢?为什么它在SqlDev上工作,而不是在c#中?
回答我自己的问题:
看来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#十进制之间不兼容。限制Oracle的小数点,以避免无效的强制转换异常。
希望这对其他人有帮助!
我知道这个帖子真的很老了。然而,我有一个类似的问题。
最好的解决方案我必须使用Oracle方法TO_BINARY_DOUBLE在Oracle十进制列
我知道这个问题已经有人回答了,但是我还发现了另一个我也使用的替代方法。我在给我带来麻烦的场地上使用了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
解决这个问题更方便的方法是在OracleDataAdapter中使用SuppressGetDecimalInvalidCastException
:
var table = new DataTable();
await using var connection = new OracleConnection(connectionString);
var command = new OracleCommand(queryString, connection)
{
CommandTimeout = commandTimeout
};
using var adapter = new OracleDataAdapter(command) { SuppressGetDecimalInvalidCastException = true };
await Task.Run(() => adapter.Fill(table));
来自文档:
该属性指定是否抑制InvalidCastException如果Oracle NUMBER值,则返回一个四舍五入的28精度值精度大于28。