OracleCommandオブジェクトのExecuteReaderメソッドは、OracleDataReaderオブジェクトを戻します。このオブジェクトは、読取り専用および順方向専用の結果セットです。
この項では、OracleDataReaderオブジェクトに関する次の情報を示します。
OracleDataReaderクラスは、2つのタイプの型指定アクセッサを提供します。
表3-11には、ODP.NETがサポートするすべてのOracleデータベースのネイティブ・タイプと、それらに対応した、Oracleネイティブ・タイプを表す.NETタイプがリストされています。Oracleネイティブ・タイプを表すために複数の.NETタイプが使用される場合、最初の.NETタイプ・エントリは、Oracleネイティブ・タイプを最も適切に表します。3列目は、.NETタイプとして取得されるOracleネイティブ・タイプに対して起動される有効な型指定アクセッサを示します。無効な型指定アクセッサが列に使用された場合、InvalidCastExceptionがスローされます。Oracleネイティブ・データ型は、データベースのバージョンに依存します。このため、Oracleデータベースの以前のバージョンでは使用できないデータ型もあります。
表3-11 .NETタイプのアクセッサ
| Oracleネイティブ・データ型 | .NETタイプ | 型指定アクセッサ |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OracleDataReaderオブジェクトの一部のメソッドおよびプロパティでは、列の精度とスケールに基づいて、ODP.NETでNUMBER列を.NETタイプにマップする必要があります。これらのメンバーは、次のとおりです。
Itemプロパティ
GetFieldTypeメソッド
GetValueメソッド
GetValuesメソッド
ODP.NETは、次の.NETタイプを順に検証して、列の値の範囲全体を表すリストの最初の.NETタイプを選択することで、適切な.NETタイプを決定します。
System.Byte
System.Int16
System.Int32
System.Int64
System.Single
System.Double
System.Decimal
列の値の範囲全体を表す.NETタイプが存在しない場合、列値をSystem.Decimalタイプとして表そうとします。列の値をSystem.Decimalとして表せない場合、例外が発生します。
たとえば、2つの列をNUMBER(4,0)およびNUMBER(10,2)として定義してみます。列の値の範囲全体を表す前のリストでは、最初の.NETタイプはそれぞれSystem.Int16とSystem.Doubleです。次に、列をNUMBER(20,10)として定義してみます。この場合、列の値の範囲全体を表す.NETタイプが存在しないため、列の値をSystem.Decimalタイプとして戻そうとします。列の値をSystem.Decimalタイプとして表せない場合、例外が発生します。
OracleDataAdapterのFillメソッドは、OracleDataReaderオブジェクトを使用して、.NETタイプのDataTableまたはDataSetを移入あるいはリフレッシュします。その結果、DataTableまたはDataSetのNUMBER列を表すために使用される.NETタイプも、その列の精度とスケールに依存します。
ODP.NETは、データベースのデータ型をネイティブに表すプロバイダ固有のタイプを公開します。これらのODP.NETタイプにより、対応する.NETタイプよりもパフォーマンスおよび機能性が上回る機能が提供される場合があります。ODP.NETタイプは、それぞれの型指定アクセッサをコールすることで、OracleDataReaderオブジェクトから取得できます。
表3-12には、ODP.NETがOracleネイティブ・タイプのODP.NETタイプを取得する際に使用する有効なタイプのアクセッサがリストされています。
表3-12 ODP.NETタイプのアクセッサ
| Oracleネイティブ・データ型 | ODP.NETタイプ | 型指定アクセッサ |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OracleRef |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODP.NETは、OracleDataReaderオブジェクトでReadメソッドを起動中に、データベースから行をフェッチおよびキャッシュします。この操作により取得されるLONGおよびLONG RAW列データの量は、InitialLONGFetchSizeにより決定されます。InitialLONGFetchSizeが、0、0より大きな値および-1に設定されている場合の動作の違いは、次の各項で説明します。
|
注意: ODP.NETでは、CommandBehavior.SequentialAccess列挙値はサポートされていません。このため、LONGおよびLONG RAWデータはランダムにフェッチできます。 |
OracleDataReaderオブジェクトでReadメソッドを起動中に、LONGまたはLONG RAW列データに対して指定された、InitialLONGFetchSizeの文字数またはバイト数がキャッシュに取り出されます。
デフォルトでは、InitialLONGFetchSizeは0に設定されています。この場合ODP.NETは、OracleDataReader オブジェクト上でのReadメソッドの起動中、LONGまたはLONG RAW列データのいずれもフェッチしません。データがキャッシュされないため、データベースのラウンド・トリップの原因となるLONGまたはLONG RAW列に対して型指定アクセッサ・メソッドが明示的に起動されると、LONGまたはLONG RAWデータがフェッチされます。
InitialLONGFetchSizeが0より大きな値に設定された場合、OracleDataReaderオブジェクトでReadメソッドを起動すると、ODP.NETにより、指定された量のデータがキャッシュされます。アプリケーションが型指定アクセッサ・メソッドによりInitialLONGFetchSize以下のデータ量を要求した場合、データベース・ラウンドトリップは発生しません。ただし、InitialLONGFetchSizeを超えるデータをフェッチするには、追加のデータベース・ラウンドトリップが必要です。
InitialLONGFetchSize文字数またはバイト数よりも多くのデータを取得するには、選択リストに次のいずれかが必要です。
主キー
ROWID
一意の列: (一意制約が定義されたか、または一意索引が作成された1セットの列として定義されたもの。セット内の少なくとも1列には、ここで定義されたNOT NULL制約があります)
選択リストに主キー列(ROWID)または一意の列がない状態で、LONGまたはLONG RAWデータ全体をフェッチするには、OracleCommandオブジェクトのInitialLONGFetchSizeプロパティのサイズを、検索に必要な文字数またはバイト数以上に設定します。
OracleDataReaderオブジェクトで適切な型指定アクセッサ・メソッド(LONGの場合GetChars、GetOracleStringまたはGetString、LONG RAWの場合GetOracleBinaryまたはGetBytes)がコールされたときに、LONGまたはLONG RAWデータが戻されます。
InitialLONGFetchSizeを-1に設定すると、選択リストに主キー、ROWIDまたは一意の列を必要とせずに、SELECT問合せに対してデータベースからLONGまたはLONG RAWデータ全体をフェッチできます。
InitialLONGFetchSizeが-1に設定されると、OracleDataReaderオブジェクトでReadメソッドを起動中に、LONGまたはLONG RAWデータ全体が取り出され、キャッシュされます。OracleDataReaderオブジェクトでGetString、GetOracleString、GetChars、GetBytesまたはGetOracleBinaryをコールすると、列データ全体が戻されます。
ODP.NETは、OracleDataReaderオブジェクトでReadメソッドを起動中に、データベースから行をフェッチおよびキャッシュします。この操作により取得されるLOB列データの量は、InitialLOBFetchSizeにより決定されます。
次の各項では、InitialLOBFetchSizeが、0、0より大きな値および-1に設定されている場合の動作の違いを説明します。
デフォルトで、InitialLOBFetchSizeプロパティを0に設定すると、OracleDataReaderでメソッドGetOracleBlob()とGetOracleClob()メソッドが起動され、OracleBlobオブジェクトおよびOracleClobオブジェクトを取得できます。
InitialLOBFetchSizeが0(ゼロ)に設定されている場合、アプリケーションがCLOB列およびBLOB列に対してコールできる型指定アクセッサ・メソッドの全リストを次に示します。
BLOB列に対してコールできるメソッド
GetBytes
GetValue
GetValues
GetOracleBinary
GetOracleBlob
GetOracleBlobForUpdate
GetOracleValue
GetOracleValues
CLOB列に対してコールできるメソッド
GetChars
GetString
GetValue
GetValues
GetOracleString
GetOracleClob
GetOracleClobForUpdate
GetOracleValue
GetOracleValues
InitialLOBFetchSizeを0より大きな値に設定すると、OracleDataReaderオブジェクトに対するReadメソッドを起動中に、ODP.NETにより、選択された各LOBに対してInitialLOBFetchSizeの文字数またはバイト数までのLOBデータがキャッシュされます。
この項では、キャッシュされるInitialLOBFetchSize文字数またはバイト数よりも多くのデータをフェッチする方法について説明します。この機能は、Oracle Database 10gリリース2(10.2)以上では変更されています。
Oracle Database 10gリリース2(10.2)以前のリリースでは、InitialLOBFetchSize文字数またはバイト数よりも多くのデータを取得するには、問合せ選択リストに次のいずれかが必要です。
主キー
ROWID
一意の列: (一意制約が定義されたか、または一意索引が作成された1セットの列として定義されたもの。セット内の少なくとも1列には、ここで定義されたNOT NULL制約があります)
OracleDataReaderオブジェクトで適切な型指定アクセッサ・メソッドがコールされると、要求されたLOBデータがデータベースからフェッチされます。
選択リストに主キー列(ROWID)または一意の列がない場合、LOBデータ全体をフェッチするには、OracleCommandオブジェクトのInitialLOBFetchSizeプロパティのサイズを、検索に必要な文字数またはバイト数以上に設定します。
InitialLOBFetchSizeプロパティを0(ゼロ)以外の値に設定すると、GetOracleBlob、GetOracleClob、GetOracleBlobForUpdateおよびGetOracleClobForUpdate型指定アクセッサ・メソッドが無効になります。
Oracle Database 10gリリース2(10.2)以上では、InitialLOBFetchSizeプロパティに設定された値に関係なく、型指定アクセッサが起動されるとLOBデータ全体が戻されます。指定されたInitialLOBFetchSizeよりも多くのデータを取得するために、主キー、ROWIDまたは一意の列を問合せ選択リストに含める必要はありません。
Oracle Database 10gリリース2以上では、InitialLOBFetchSizeが0より大きな値であっても、GetOracleBlob、GetOracleClob、GetOracleBlobForUpdateおよびGetOracleClobForUpdateメソッドを起動できるようになりました。
InitialLOBFetchSizeが0より大きな値に設定されている場合に、アプリケーションがCLOB列およびBLOB列に対してコールできる型指定アクセッサ・メソッドの全リストを次に示します。
BLOB列に対してコールできるメソッド
GetBytes
GetValue
GetValues
GetOracleBinary
GetOracleBlob
GetOracleBlobForUpdate
GetOracleValue
GetOracleValues
CLOB列に対してコールできるメソッド
GetChars
GetString
GetValue
GetValues
GetOracleString
GetOracleClob
GetOracleClobForUpdate
GetOracleValue
GetOracleValues
InitialLOBFetchSizeを-1に設定することで、選択リストに主キー、ROWIDまたは一意の列がない場合も、SELECT問合せに対してデータベースからLOBデータ全体をフェッチできます。InitialLOBFetchSizeが-1に設定されると、OracleDataReaderオブジェクトでReadメソッドを起動中に、LOB列データ全体がフェッチおよびキャッシュされます。OracleDataReaderオブジェクトでGetString、GetOracleString、GetChars、GetBytesまたはGetOracleBinaryをコールすると、すべてのデータを取得できます。
この項では、InitialLOBFetchSizeプロパティが-1に設定されている場合に、CLOBおよびBLOBデータ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
表3-13では、CLOBデータ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
表3-13 OracleDataReader CLOBメソッド
| サポート対象 | サポート対象外 |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
表3-14では、BLOBデータ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
この項では、異なる状況における、InitialLOBFetchSizeプロパティの様々な設定のメリットおよびデメリットについて説明します。また、使用しているデータベース・リリースに応じたパフォーマンスの強化方法についても説明します。
InitialLOBFetchSizeプロパティをゼロ以外の値に設定すると、パフォーマンスが向上する場合があります。InitialLOBFetchSizeプロパティを使用すると、OracleBlobオブジェクトまたはOracleClobオブジェクトを使用して基礎となるLOBデータを検索するよりもパフォーマンスが向上します。これは、アプリケーションがOracleDataReaderオブジェクトからOracleBlobオブジェクトおよびOracleClobオブジェクトを取得する必要がなく、LOB列データのサイズがあまり大きくない場合に当てはまります。問合せで戻されるLOB列データのサイズがすべての行でほぼ同じ場合、InitialLOBFetchSizeは特に便利です。
通常、InitialLOBFetchSizeプロパティは、問合せで戻される行の80%以上のLOBデータのサイズより大きい値に設定することをお薦めします。たとえば、LOBデータのサイズが行の80%で1KB未満で、行の20%で1MB以上である場合、InitialLOBFetchSizeプロパティを1KBに設定します。
アプリケーションで、パフォーマンスとOracleBlobおよびOracleClob機能のどちらをとるかを選択する必要はありません。InitialLOBFetchSizeプロパティを設定すると、パフォーマンスは向上し、OracleBlobオブジェクトおよびOracleClobオブジェクトを使用する自由度はそのままです。
LOBデータのサイズが不明であったり、LOBデータのサイズが不規則に変化する場合は、InitialLOBFetchSizeプロパティをデフォルト値の0のままにしてください。これでも、ほとんどの場合でパフォーマンスが改善されます。
大部分の行についてInitialLOBFetchSizeプロパティのサイズをLOBデータ・サイズ以上に設定すると、パフォーマンスが劇的に改善されます。通常、InitialLOBFetchSizeプロパティは、問合せで戻される行の80%以上のLOBデータのサイズより大きい値に設定することをお薦めします。たとえば、LOBデータのサイズが行の80%で1KB未満で、行の20%で1MB以上である場合、InitialLOBFetchSizeプロパティを1KBに設定します。
アプリケーションのパフォーマンスは、アプリケーションがフェッチする必要のある行数と、行の検索に必要なデータベース・ラウンドトリップの回数に依存します。
FetchSizeプロパティは、データベース・ラウンドトリップからフェッチされたデータをキャッシュするためにODP.NETが割り当てるメモリー・サイズの合計をバイトで表したものです。
FetchSizeプロパティは、状況に応じてOracleCommandまたはOracleDataReaderオブジェクトで設定できます。また、OracleCommandオブジェクトのFetchSizeプロパティはOracleDataReaderオブジェクトにより継承され、変更できます。
FetchSizeプロパティをOracleCommandオブジェクトで設定した場合、新しく作成されたOracleDataReaderは、OracleCommandオブジェクトのFetchSizeプロパティを継承します。この継承されたFetchSizeは、そのままにしておくか、継承された値を上書きするように変更できます。OracleDataReaderオブジェクトのFetchSizeプロパティは、最初のReadメソッドを起動する前に変更できます。このメソッドは、FetchSizeプロパティで指定されたメモリーを割り当てます。データベースからの後続のフェッチはすべて、そのOracleDataReaderに割り当てられた同じキャッシュを使用します。このため、最初のReadメソッドを起動した後にFetchSizeを変更しても影響はありません。
FetchSizeプロパティを微調整することで、アプリケーションは、メモリー使用率、および1回のデータベース・ラウンドトリップでフェッチされる行数を制御して、パフォーマンスを向上させることができます。たとえば、問合せが100行を戻し、各行が1024バイトある場合、FetchSizeプロパティを102400に設定すると、1回のデータベース・ラウンドトリップで100行をフェッチできます。同じ問合せで、FetchSizeプロパティを10240に設定すると、100行を検索するのに10回のデータベース・ラウンドトリップが必要になります。アプリケーションが結果セットからすべての行をフェッチする必要がある場合、最初の使用例の方が2番目の使用例より高速になります。ただし、アプリケーションが結果セットから最初の10行のみをフェッチする必要がある場合、100行ではなく10行のみをフェッチするため、2番目の使用例の方がパフォーマンスが向上します。
OracleCommandオブジェクトのRowSizeプロパティは、SELECT文の実行後に行サイズ(バイト)とともに移入されます。FetchSizeプロパティは、RowSizeプロパティとデータベース・ラウンドトリップごとにフェッチされる行数の積に設定することで、RowSizeプロパティに相対的な値に設定できます。
たとえば、FetchSizeをRowSize * 10に設定すると、OracleDataReaderオブジェクトでは、データベース・ラウンドトリップごとに10行のみが強制的にフェッチされます。各列のデータ長によってRowSizeが変わることはありません。RowSizeは、SELECT文が実行されるデータベース表のメタデータ情報から正確に決定されます。
RowSizeプロパティを使用すると、次の項で説明するように、設計時または実行時にFetchSizeプロパティを設定できます。
HKLM¥Software¥Oracle¥ODP.NET¥ version¥FetchSizeレジストリ・エントリは、特定のバージョンのODP.NETを使用するすべてのアプリケーションに対するデフォルトの結果セットのフェッチ・サイズをバイト単位で指定するように設定できます。または、アプリケーション構成ファイルまたはweb.configファイルのFetchSize属性で、特定のアプリケーションに対するデフォルト値を指定できます。デフォルトのフェッチ・サイズは65536バイトです。この値は、実行時にアプリケーションのFetchSizeプロパティをOracleCommandまたはOracleDataReaderに対してプログラムで設定することによって無視できます。
特定のSELECT文の行サイズが前の実行ですでにわかっている場合、OracleCommandオブジェクトのFetchSize値は、設計時に、その行サイズとアプリケーションがデータベース・ラウンドトリップごとにフェッチする必要がある行数の積に設定できます。OracleCommandオブジェクトのFetchSize値セットは、OracleCommandオブジェクトでExecuteReaderメソッドを起動したときに作成されたOracleDataReaderオブジェクトにより継承されます。OracleCommandオブジェクトでFetchSizeを設定するのではなく、OracleDataReaderで直接FetchSizeを設定することもできます。いずれの場合にも、実行時にRowSizeプロパティ値にアクセスしなくても、FetchSizeは設計時に設定されます。
設計時に行サイズがわからないアプリケーションでは、OracleCommandオブジェクトのRowSizeプロパティを使用して、OracleDataReaderオブジェクトのFetchSizeプロパティを設定できます。RowSizeプロパティは、行のサイズに基づいて、動的な方法でFetchSizeプロパティを設定します。
OracleCommandオブジェクトでExecuteReaderメソッドを起動してOracleDataReaderオブジェクトを取得した後に、RowSizeプロパティが行のサイズ(バイト)とともに移入されます。RowSizeプロパティを使用することで、アプリケーションは、OracleDataReaderオブジェクトのFetchSizeプロパティを、RowSizeプロパティ値とアプリケーションがデータベース・ラウンドトリップごとにフェッチする必要がある行数の積に動的に設定できます。この使用例では、実行時にRowSizeプロパティにアクセスすることでFetchSizeが設定されます。