きよくらの備忘録

「三日坊主と呼ばせない!日記」改め。主にソフトウェア開発関連の話題。

DapperでOracleのNUMBERと.NETのBooleanをマッピングする

Oracleはテーブルのカラム定義で使える型には真偽値(bool/boolean)型がありません*1

そのため、NUMBER型で0,-1を入れたりCHAR型で0,1を入れたりVARCHAR型でTRUEとFALSEを入れつつ、制約やトリガと組み合わせて使ってるケースが多いのではないかと思います。

 

一方、.NETには真偽値型(Boolean/bool)がありますので、DBでどんな型で表現されていようが.NETのコードの世界ではちゃんと真偽値型で扱いたいです。

 

このあたり、Dapperにお任せするとどのようになるかを少し試してみました。

NUMBER(Oracle) to bool(C#

まずはクエリの結果をオブジェクトにマッピングする場合。 結論から言うと下記の通り。

  • NUMBER型で-1/0はbool型のtrue/falseにマッピングする
  • 文字列型の'-1'/'0'は例外が出てマッピングされない

コード例はこんな感じです

その他、NUMBERの1もtrueにマッピングされました。試してないですが、0以外の数値はtrueにマッピングするのかもしれません。

 

bool(C#) to NUMBER(Oracle

次はパラメータとしてNUMBER型のフィールドにマッチさせたいところにbool型を当てるとどうなるか試してみました。

こちらも先に結論言うと、これはNG。こんな感じで例外が出ます。

[ArgumentException: 値が有効な範囲にありません。] Oracle.DataAccess.Client.OracleParameter.set_DbType(DbType value) +121 ParamInfo902ca3ce-02f9-402d-80d5-90c8ea8ddff1(IDbCommand , Object ) +145 Dapper.SqlMapper.SetupCommand(IDbConnection cnn, IDbTransaction transaction, String sql, Action`2 paramReader, Object obj, Nullable`1 commandTimeout, Nullable`1 commandType) in c:\Dev\Dapper\Dapper NET40\SqlMapper.cs:2020 Dapper.d__d`1.MoveNext() in c:\Dev\Dapper\Dapper NET40\SqlMapper.cs:854

ODPのDbTypeにbool型を考慮したものが無いので、例外になっているようです。当たり前といえば当たり前ですね。

ですので、一度引き当てる数値に直してから拡張メソッドに渡してやるのが適切だと思います。場合によっては、trueが-1か1かテーブルの仕様で変わってくることもあると思いますし。

 

 

(蛇足ですが、こちらのパターンの場合は文字列で'-1'などを渡した場合は上手くいきます。Dapper的にはバインドするパラメータの型を相手のDBが知っている型に設定できればいいので、文字列なら問題ありません。その後はOracleがどう扱うか次第です。なので、Oracleが暗黙で数値としてみなせる'-1'とか'9'とかはクエリは通りますが、数値型のカラムと比較できない'true'とか'hogehoge'等を与えるとOracleがエラーを返してきます。)

*1:PL/SQLではboolean型がある