OracleDataAdapter.Fill() から DataTable にデータを入力するときに「指定されたキャストは無効です」というメッセージが表示される 質問する

OracleDataAdapter.Fill() から DataTable にデータを入力するときに「指定されたキャストは無効です」というメッセージが表示される 質問する

この質問は Google (または StackOverflow) のどこにも見つからないようで、本当に驚きました。そこで、同じ状況にある他の人の役に立つように、ここに投稿します。

Oracle Sql Developer で正常に実行される SQL クエリがありますが、結果を取得するためにC#を使用して実行すると、エラー ( ) が発生します。adapter.Fill(table)Specified cast is not validSystem.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_totalNumber(19,4) 型であり、Oracle アダプターが小数点を期待していることがわかります。では、どのようなキャストが行われているのでしょうか。SqlDev では機能するのに、C# では機能しないのはなぜでしょうか。

ベストアンサー1

私自身の質問に答えます:

したがって、Oracle の数値型は C# の 10 進数型よりも多くの小数点以下の桁数を保持できるようです。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# の 10 進数の間には互換性がありません。無効なキャスト例外を回避するには、Oracle の 10 進数の桁数を制限してください。

これが他の誰かの役に立つことを願います!

おすすめ記事