Oracle Numberデータ型のデフォルト・マッピングおよびカスタマイズ

この項では、デフォルトの数値マッピング動作と、アプリケーションのためにそれをカスタマイズする方法について説明します。.NET構成ファイルでカスタム・マッピングを構成して、整数値を表すOracleの各Number(p,0)のデフォルト・マッピングを上書きできます。

整数を表すOracle NUMBERデータ型には、正確に同じ範囲で許容される値を持つ、一致する.NET整数データ型がありません。ODP.NETは、カスタムのデータ型マッピングを必要とせずに.NETの整数型値をOracleデータベースに格納できる、デフォルトのマッピングを使用します。ただし、データベースから値を取得するとき、OracleのNUMBER(p,0)列データは、.NETデータ型で保持できるより大きくなる場合があります。

たとえばEntity Framework 6では、OracleのNUMBER(3,0)はデフォルトでNET Byteにマッピングされます。OracleのNUMBER(3,0)には最大999までの値を格納でき、.NETのBYTEには最大255までの値を格納できます。Oracleのデータが255を超えると想定される場合は、マッピングをより大きい数値データ型、たとえば.NETのInt16に変更してください。このようにカスタム・マッピングを設定すると、エラーを発生させずに、.NETでデータを使用できます。このようなカスタム・マッピングを使用するときには、OracleのNUMBER(3,0)が保持できる制限を超えて.NETのInt16を挿入しないよう注意してください。Int16.MaxValue (すなわち32,767)をNUMBER(3,0)列に挿入すると、Oracle Databaseエラーが発生します。

Entity Framework 6マッピングおよびカスタマイズ

管理対象および管理対象外のODP.NET Entity Framework 6アプリケーションは、.NET構成ファイルを使用してカスタム・データ型マッピングを設定できます。マッピングは、Code First、Database FirstおよびModel Firstのユースケースで機能します。この形式は、管理対象および管理対象外のODP.NETが構成値を設定する方法を統合し、オートコンプリートをサポートするため、古いバージョンよりも改善されています。

次に、ODP.NET管理対象ドライバのedmMappingsセクションの例を示します。

<oracle.manageddataaccess.client>
  <version number="*">
    <edmMappings>
      <edmNumberMapping>
        <add NETType="bool" MinPrecision="1" MaxPrecision="1" DBType="Number" />
        <add NETType="byte" MinPrecision="2" MaxPrecision="3" DBType="Number" />
        <add NETType="int16" MinPrecision="4" MaxPrecision="5" DBType="Number" />
        <add NETType="int32" MinPrecision="6" MaxPrecision="10" DBType="Number" />
        <add NETType="int64" MinPrecision="11" MaxPrecision="19" DBType="Number" />
      </edmNumberMapping>
    </edmMappings>
  </version>
</oracle.manageddataaccess.client>

ここで

  • DBTypeはOracle Databaseデータ型です

  • NETTypeは、Oracleデータ型がマップされる.NETデータ型です

  • MinPrecisionは、Oracleデータ型が.NET型にマップされる最小範囲です

  • MaxPrecisionは、Oracleデータ型が.NET型にマップされる最大範囲です

次に、ODP.NET管理対象外ドライバのedmmappingsセクションの例を示します。開始タグと終了タグ以外は、管理対象ドライバと完全に同じ形式です。

<oracle.unmanageddataaccess.client>
  <version number="*">
    <edmMappings>
      <edmNumberMapping>
        <add NETType="bool" MinPrecision="1" MaxPrecision="1" DBType="Number" />
        <add NETType="byte" MinPrecision="2" MaxPrecision="3" DBType="Number" />
        <add NETType="int16" MinPrecision="4" MaxPrecision="5" DBType="Number" />
        <add NETType="int32" MinPrecision="6" MaxPrecision="10" DBType="Number" />
        <add NETType="int64" MinPrecision="11" MaxPrecision="19" DBType="Number" />
      </edmNumberMapping>
    </edmMappings>
  </version>
</oracle.unmanageddataaccess.client>

新しいデフォルト・マッピング

Entity Framework 6では、ODP.NET 12.1.0.2は、Code First、Database FirstおよびModel Firstのシナリオに適用される新しいデフォルト・マッピングを導入しました。Code First互換性をサポートするためには、次の変更が必要でした。

  • デフォルトで、.NET BooleansはOracle Number(1,0)にマップされ、逆にもマップされます

  • デフォルトで、.NET BytesはOracle Number(2,0) Number(3,0)にマップされ、逆にもマップされます

.NET構成ファイルのセクションを構成して代わりのデータ型マッピングを指定することで、このデフォルトの動作は変更できます。

ODP.NETバージョン23およびOracle Database 23ai以降、Database FirstのシナリオではOracleのBoolean列は.NETのBooleansにマップされ、Code Firstのシナリオでは.NETのBooleansはOracleのNumber(1)にマップされたままになります。

デフォルトのCode Firstマッピングをオーバーライドするには、エンティティ・プロパティにEntity Framework Fluent APIのHasColumnType("boolean")を指定します。

データ型のマッピングおよびカスタマイズの手順

カスタム・マッピングを有効にするには、EDM作成の前に、.NET構成ファイルにマッピング情報を追加します。

マッピング情報を提供する前にすでにEDMが作成されている場合、Visual Studioツールを使用するか、または手動でマッピングを変更できます。Visual Studioを使用して、EDMの「Model Browser」ページに移動します。新しいデータ型のマッピングが必要な表を右クリックし、ポップアップ・メニューから「Table Mapping」を選択します。通常は画面の一番下に「Mapping Details」ウィンドウが表示されます。必要に応じて「Column Mappings」を更新します。

マッピングを追加または削除する必要がある場合、プロジェクトの既存のEDMXファイルのCSDLマッピング・セクションでTypeの値を見つけます。それらのTypeの値を、アプリケーションで使用する.NETデータ型に追加するか、削除します。次の例では、BOOLCOLおよびBYTECOLのプロパティ・ネーム・タイプがCSDLに追加され、それぞれBooleanおよびByteにマップされています。

CSDLカスタマイズ前のマッピングの例:

<Property Name="INT16COL" Type="Int16" Nullable="false" /> 

CSDLカスタマイズ後のマッピングの例:

<Property Name="BOOLCOL" Type="Boolean" Nullable="false" /> 
<Property Name="BYTECOL" Type="Byte" Nullable="false" /> 
<Property Name="INT16COL" Type="Int16" Nullable="false" />

予定しているマッピングの変更に応じて、これらのカスタマイズの可能性を組み合せて使用できます。多数の表および多数の列でマッピングの変更が必要な場合、EDMXファイルを削除してデータ・モデルを再生成する方法が最も効率的です。少数の表および多数の列で変更が必要な場合、影響を受ける表を削除してEDMXファイルを保存し、「Update Model from Database...」 を選択してこれらの表を再度含めます。単一の表および1つまたは2つの列のみで変更が必要な場合、手動で、または「Mapping Details」ウィンドウを使用してEDMXを変更します。

ノート:

関数インポートからの複合型を作成するためにEDMウィザードを使用する場合、指定される任意のカスタムEDMタイプ・マッピングは自動では適用されません。EDMウィザードはデフォルト・タイプ・マッピングを使用します。開発者は、結果複合型を手動で編集する必要があります。開発者は複合型が生成された後にこのプロセスを開始します。BooleanではなくDecimalなど望ましくないタイプ・マッピングを持つ複合オブジェクトのあらゆる型宣言(フィールド、プロパティ、コンストラクタ・パラメータなど)は、望ましいタイプに手動で編集してください。

StoreGeneratedPattern列挙体

次の各項では、Identity属性およびVirtual列について説明します。

Identity属性

Oracle Database 12c (12.1)およびそれ以降のバージョンでは、Identity属性列の表またはビューをサポートしています。Oracleには、3つのIdentity属性タイプがあります。EDMウィザードによって、表またはビューを含むOracle Identity属性からデータ・モデルが生成される際に、3つのOracle Identity属性タイプのそれぞれについて、ODP.NETによって.edmxファイルのIdentityStoreGeneratedPatternの値が設定されます。Identity属性に関連する列では、INSERTの間に、サーバーで生成された値が使用されます。したがって、アプリケーション開発者は、順序やトリガーを作成する必要がありません。.NETアプリケーション自体がIdentity属性を設定する場合、この値は無視されます。

Virtual列

Oracle Databaseのバージョンでは、式をVirtual列(Generated列とも呼ばれます)として、実表に直接格納できます。Virtual列を挿入または更新することはできません。ODP.NETによって、Virtual列のEFモデルのComputedStoreGeneratedPatternは、自動で設定されません。エラーを回避するために、アプリケーション開発者は、モデル生成後のVirtual列のComputedStoreGeneratedPatternの値を追加するか、または変更する必要があります。これにより、SaveChanges()の呼出し時に、Virtual列はINSERTおよびUPDATEから除外されます。

カスタム・マッピングの使用時の比較エラーの解決

.NET構成ファイルのカスタム・マッピングを変更した場合、変更によって発生した比較エラーを解決するには、データ・モデルを再生成します。

場合によっては、カスタム・マッピングを使用するプロジェクトがVisual Studioによってロードされる際に、カスタム・マッピングが原因で比較エラーが発生することがあります。特定のシナリオの1つは、Visual Studioが以前はなかったエラーを生成するようになった既存のカスタム・マッピング付きのプロジェクトを開くときです。この場合、次の回避策を使用できます。

  1. Visual Studioのヘルプ「About Microsoft Visual Studio」を開きます。「OK」をクリックしてダイアログ・ボックスを終了します。

    かわりに、Server Explorerで使用する接続を開きます。

  2. プロジェクトを再コンパイルしてコンパイル・エラーを消去します。

カスタムINSERT、UPDATEおよびDELETEストアド・プロシージャでのブール・パラメータおよびguidパラメータのマッピング

ストアド・プロシージャのマッピングにカスタムINSERT、UPDATEまたはDELETEストアド・プロシージャを使用すると、次のエラーが発生する場合があります。

エラー2042: 指定されたパラメータ・マッピングが無効です。

これは、NumberパラメータがBoolean属性にマップされた場合またはRAWパラメータがGuid属性にマップされた場合に発生します。

解決策として、SSDLでストアド・プロシージャのNumberパラメータにPrecision="1"を、RAWパラメータにMaxLength="16"を手動で追加します。