3.10 OracleDataReaderオブジェクトからのデータの取得
OracleCommand
オブジェクトのExecuteReader
メソッドは、OracleDataReader
オブジェクトを戻します。このオブジェクトは、読取り専用および順方向専用の結果セットです。
この項では、OracleDataReader
オブジェクトに関する次の情報を示します。
3.10.1 OracleDataReader型指定アクセッサ
OracleDataReader
クラスは、2つのタイプの型指定アクセッサを提供します。
3.10.1.1 .NETタイプのアクセッサ
表3-14には、ODP.NETがサポートするすべてのOracleデータベースのネイティブ・タイプと、それらに対応した、Oracleネイティブ・タイプを表す.NETタイプがリストされています。Oracleネイティブ・タイプを表すために複数の.NETタイプが使用される場合、最初の.NETタイプ・エントリは、Oracleネイティブ・タイプを最も適切に表します。3列目は、.NETタイプとして取得されるOracleネイティブ・タイプに対して起動される有効な型指定アクセッサを示します。無効な型指定アクセッサが列に使用された場合、InvalidCastException
がスローされます。Oracleネイティブ・データ型は、データベースのバージョンに依存します。このため、Oracle Databaseの以前のバージョンでは使用できないデータ型もあります。
表3-14 .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タイプも、その列の精度とスケールに依存します。
3.10.1.2 ODP.NETタイプのアクセッサ
ODP.NETは、データベースのデータ型をネイティブに表すプロバイダ固有のタイプを公開します。これらのODP.NETタイプにより、対応する.NETタイプよりもパフォーマンスおよび機能性が上回る機能が提供される場合があります。ODP.NETタイプは、それぞれの型指定アクセッサをコールすることで、OracleDataReader
オブジェクトから取得できます。
表3-15には、ODP.NETがOracleネイティブ・タイプのODP.NETタイプを取得する際に使用する有効なタイプのアクセッサがリストされています。
表3-15 ODP.NETタイプのアクセッサ
Oracleネイティブ・データ型 | ODP.NETタイプ | 型指定アクセッサ |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OracleRef |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
関連項目:
すべてのODP.NETタイプのリストは、ODP.NETタイプの概要を参照してください
3.10.2 LONGおよびLONG RAWデータの取得
ODP.NETは、OracleDataReader
オブジェクトでRead
メソッドを起動中に、データベースから行をフェッチおよびキャッシュします。この操作により取得されるLONG
およびLONG
RAW
列データの量は、InitialLONGFetchSize
により決定されます。InitialLONGFetchSize
が、0
、0
より大きな値および-1
に設定されている場合の動作の違いは、次の各項で説明します。
注意:
ODP.NETでは、CommandBehavior.SequentialAccess
列挙値はサポートされていません。このため、LONG
およびLONG
RAW
データはランダムにフェッチできます。
3.10.2.1 InitialLONGFetchSizeを0(ゼロ)または0(ゼロ)より大きな値に設定
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
データが戻されます。
3.10.2.2 InitialLONGFetchSizeを-1に設定
InitialLONGFetchSize
を-1
に設定すると、選択リストに主キー、ROWID
または一意の列を必要とせずに、SELECT問合せに対してデータベースからLONG
またはLONG
RAW
データ全体をフェッチできます。
InitialLONGFetchSize
が-1
に設定されると、OracleDataReader
オブジェクトでRead
メソッドを起動中に、LONG
またはLONG
RAW
データ全体が取り出され、キャッシュされます。OracleDataReader
オブジェクトでGetString
、GetOracleString
、GetChars
、GetBytes
またはGetOracleBinary
をコールすると、列データ全体が戻されます。
3.10.3 LOBデータの取得
ODP.NETは、OracleDataReader
オブジェクトでRead
メソッドを起動中に、データベースから行をフェッチおよびキャッシュします。この操作により取得されるLOB列データの量は、InitialLOBFetchSize
により決定されます。
InitialLOBFetchSize
が0
、0
より大きな値または -1
に設定されている場合に、アプリケーションがCLOB
列およびBLOB
列に対してコールできる型指定アクセッサ・メソッドの全リストを次に示します。
-
BLOB
列に対してコールできるメソッド-
GetBytes
-
GetValue
-
GetValues
-
GetOracleBinary
-
GetOracleBlob
-
GetOracleBlobForUpdate
-
GetOracleValue
-
GetOracleValues
-
-
CLOB
列に対してコールできるメソッド-
GetChars
-
GetString
-
GetValue
-
GetValues
-
GetOracleString
-
GetOracleClob
-
GetOracleClobForUpdate
-
GetOracleValue
-
GetOracleValues
-
次の各項では、InitialLOBFetchSize
が、0
、0
より大きな値および-1に設定されている場合の動作の違いを説明します。
3.10.3.1 InitialLOBFetchSizeを0(ゼロ)に設定
デフォルトでは、InitialLOBFetchSize
プロパティは0です。この値では、LOBを選択した場合にそのクライアントLOBデータのフェッチをOracleDataReader
Read
の後まで(アクセッサを使用した場合など)遅延するようODP.NETに指定します。LOBの各値は、個々にアクセスされた時点にのみ取得されます。
このような取得方法を使用する利点は、クライアントのメモリーおよび帯域幅が節約されるということです。選択したLOBがきわめて大きい、またはエンド・ユーザーがすぐには使用する必要がない場合、あるいはその両方の場合、すべて同時ではなく必要に応じてLOBを取得する方がアプリケーションのパフォーマンスが向上します。
3.10.3.2 InitialLOBFetchSizeを0(ゼロ)より大きな値に設定
InitialLOBFetchSize
を0
より大きな値に設定すると、OracleDataReader
オブジェクトに対するRead
メソッドを起動中に、ODP.NETにより、選択された各LOBに対してInitialLOBFetchSize
の文字数またはバイト数までのLOBデータがキャッシュされます。最大値は2,147,483,647 (2GB)です。選択したLOBの合計サイズがこの数値より小さい場合は、LOBデータ全体が読み取られます。
1回または複数回のデータベース・ラウンドトリップですべてのLOBエントリをプリフェッチすると、ラウンドトリップが減るためアプリケーションのパフォーマンスが向上します。このアプローチは、大部分のLOBが小さい、またはエンド・ユーザーがほぼ即時に使用する場合、あるいはその両方の場合に最も利点を発揮します。フェッチ・サイズが大きくなるとメモリー消費量が増えるのが欠点です。
この項では、キャッシュされるInitialLOBFetchSize
文字数またはバイト数よりも多くのデータをフェッチする方法について説明します。
InitialLOBFetchSize
プロパティに設定された値に関係なく、型指定アクセッサが起動されると残りのLOBデータが戻されます。指定されたInitialLOBFetchSize
よりも多くのデータを取得するために、主キー、ROWID
または一意の列を問合せ選択リストに含める必要はありません。
InitialLOBFetchSize
が0
より大きな値であっても、GetOracleBlob
、GetOracleClob
、GetOracleBlobForUpdate
およびGetOracleClobForUpdate
メソッドを起動できるようになりました。
3.10.3.3 InitialLOBFetchSizeを-1に設定
読取り操作中に選択し、設定したLOB当たり制限によって検出されていないすべてのLOBデータをフェッチするには、InitialLOBFetchSize
を-1
に設定します。ODP.NETリリース12.1.0.2以上では、InitialLobFetchSize
を-1
に設定したときの新しいデフォルト動作が導入されました。
LegacyEntireLOBFetch = 0
のとき(デフォルト値)、LOB列で次の操作が呼び出されます。
-
OracleDataReader.GetOracleClob()
:OracleClob
オブジェクトを返します。 -
OracleDataReader.GetOracleBlob()
: returnsOracleBlob
オブジェクトを返します。 -
OracleDataReader.GetOracleClobForUpdate()
:OracleClob
オブジェクトを返します。 -
OracleDataReader.GetOracleBlobForUpdate()
:OracleBlob
オブジェクトを返します。 -
OracleDataReader.GetOracleValue()
: CLOB列に対してOracleClob
オブジェクトを返します。 -
OracleDataReader.GetOracleValue()
: BLOB列に対してOracleBlob
オブジェクトを返します。 -
OracleDataAdapter.Fill()
でProviderSpecificTypes=true
に設定:CLOB
列をOracleClob
にしてDataTable
に移入します。 -
OracleDataAdapter.Fill()
でProviderSpecificTypes=true
に設定:BLOB
列をOracleBlob
にしてDataTable
に移入します。
以前の動作を使用する場合は、ODP.NET構成でLegacyEntireLobFetch = 1
に設定します。
LegacyEntireLobFetch = 1
でInitialLOBFetchSize = -1
の場合、GetOracleClob
、GetOracleClobForUpdate
、GetOracleBlob
、GetOracleBlobForUpdate
の各メソッドはサポートされません。次の操作は、このシナリオでLOB列のために呼び出されます。
-
OracleDataReader.GetOracleClob()
:InvalidCastException()
をスローします。 -
OracleDataReader.GetOracleBlob()
:InvalidCastException()
をスローします。 -
OracleDataReader.GetOracleClobForUpdate()
:InvalidCastException()
をスローします。 -
OracleDataReader.GetOracleBlobForUpdate()
:InvalidCastException()
をスローします。 -
OracleDataReader.GetOracleValue()
:CLOB
列に対してOracleString
オブジェクトを返します。 -
OracleDataReader.GetOracleValue()
:BLOB
列に対してOracleBinary
オブジェクトを返します。 -
OracleDataAdapter.Fill()
でProviderSpecificTypes=true
に設定:CLOB
列をOracleString
にしてDataTable
に移入します。 -
OracleDataAdapter.Fill()
でProviderSpecificTypes=true
に設定:BLOB
列をOracleBinary
にしてDataTable
に移入します。
ODP.NET 12.1.0.2以前のリリースでは、InitialLOBFetchSize
を-1
に設定することで、選択リストに主キー、ROWID
または一意の列がない場合も、SELECT問合せに対してデータベースからLOBデータ全体をフェッチできます。InitialLOBFetchSize
が-1
に設定されると、OracleDataReader
オブジェクトでRead
メソッドを起動中に、LOB列データ全体がフェッチおよびキャッシュされます。OracleDataReader
オブジェクトでGetString
、GetOracleString
、GetChars
、GetBytes
またはGetOracleBinary
をコールすると、すべてのデータを取得できます。
3.10.3.3.1 InitialLOBFetchSizeが-1でLegacyEntireLobFetchが1のときにサポートされるメソッド
この項では、InitialLOBFetchSize
プロパティが-1
に設定され、LegacyEntireLobFetch
プロパティが1
に設定されている場合に、CLOB
およびBLOB
データ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
表3-16では、CLOB
データ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
表3-16 InitialLOBFetchSizeが-1でLegacyEntireLobFetchが1のときにサポートされるOracleDataReader CLOBメソッド
OracleDataReader CLOBメソッド | サポート対象 |
---|---|
|
はい |
|
はい |
|
はい |
|
はい |
|
はい |
|
はい |
|
はい |
|
いいえ |
|
いいえ |
表3-17では、BLOB
データ型に対してサポートされているメソッドとサポートされていないメソッドをリストしています。
表3-17 InitialLOBFetchSizeが-1でLegacyEntireLobFetchが1のときにサポートされるOracleDataReader BLOBメソッド
OracleDataReader BLOBメソッド | サポート対象 |
---|---|
|
はい |
|
はい |
|
はい |
|
はい |
|
はい |
|
はい |
|
いいえ |
|
いいえ |
3.10.3.4 InitialLOBFetchSizeプロパティに関連したパフォーマンス上の考慮事項
この項では、異なる状況における、InitialLOBFetchSize
プロパティの様々な設定のメリットおよびデメリットについて説明します。
アプリケーションで、パフォーマンスとOracleBlob
およびOracleClob
機能のどちらをとるかを選択する必要はありません。InitialLOBFetchSize
プロパティを設定すると、パフォーマンスは向上し、OracleBlob
オブジェクトおよびOracleClob
オブジェクトを使用する自由度はそのままです。
LOBデータのサイズが不明であったり、LOBデータのサイズが不規則に変化する場合は、InitialLOBFetchSize
プロパティをデフォルト値の0
のままにしてください。これでも、ほとんどの場合でパフォーマンスが改善されます。
大部分の行についてInitialLOBFetchSize
プロパティのサイズをLOBデータ・サイズ以上に設定すると、パフォーマンスが劇的に改善されます。通常、InitialLOBFetchSize
プロパティは、問合せで戻される行の80%以上のLOBデータのサイズより大きい値に設定することをお薦めします。たとえば、LOBデータのサイズが行の80%で1KB未満で、行の20%で1MB以上である場合、InitialLOBFetchSize
プロパティを1KBに設定します。
3.10.4 1回のデータベース・ラウンドトリップでフェッチされる行数の制御
アプリケーションのパフォーマンスは、アプリケーションがフェッチする必要のある行数と、行の検索に必要なデータベース・ラウンドトリップの回数に依存します。
3.10.4.1 FetchSizeの使用
FetchSize
プロパティは、データベース・ラウンドトリップからフェッチされたデータをキャッシュするためにODP.NETが割り当てるメモリー・サイズの合計をバイトで表したものです。
FetchSize
プロパティは、状況に応じてOracleCommand
、OracleDataReader
またはOracleRefCursor
オブジェクトで設定できます。これは、OracleDataAdapter
を使用してDataSet
またはDataTable
に移入を行う場合のフェッチ・サイズを制御します。
FetchSize
プロパティをOracleCommand
オブジェクトで設定した場合、新しく作成されたOracleDataReader
は、OracleCommand
オブジェクトのFetchSize
プロパティを継承します。この継承されたFetchSize
は、そのままにしておくか、継承された値を上書きするように変更できます。OracleDataReader
オブジェクトのFetchSize
プロパティは、最初のRead
メソッドを起動する前に変更できます。このメソッドは、FetchSize
プロパティで指定されたメモリーを割り当てます。データベースからの後続のフェッチはすべて、そのOracleDataReader
に割り当てられた同じキャッシュを使用します。このため、最初のRead
メソッドを起動した後にFetchSize
を変更しても影響はありません。
3.10.4.2 FetchSizeの微調整
FetchSize
プロパティを微調整することで、アプリケーションは、メモリー使用率、および1回のデータベース・ラウンドトリップでフェッチされる行数を制御して、パフォーマンスを向上させることができます。
たとえば、問合せが100行を戻し、各行が1024バイトある場合、FetchSize
プロパティを102400に設定すると、1回のデータベース・ラウンドトリップで100行をフェッチできます。同じ問合せで、FetchSize
プロパティを10240に設定すると、100行を検索するのに10回のデータベース・ラウンドトリップが必要になります。アプリケーションが結果セットからすべての行をフェッチする必要がある場合、最初の使用例の方が2番目の使用例より高速になります。ただし、アプリケーションが結果セットから最初の10行のみをフェッチする必要がある場合、100行ではなく10行のみをフェッチするため、2番目の使用例の方がパフォーマンスが向上します。次の10行をフェッチする場合、行1から10に割り当てられたメモリーが行11から20で再び使用されます。
FetchSize
が大きいほど、より多くのシステム・メモリーが使用されます。クライアント・システムのメモリー・リソースに制限がある場合、開発者は大きなフェッチ・サイズを設定できません。
3.10.4.3 RowSizeプロパティの使用
OracleCommand
またはOracleRefCursor
オブジェクトのRowSize
プロパティには、SELECT
文の実行後に行サイズ(バイト)が移入されます。FetchSize
プロパティは、RowSize
値とデータベース・ラウンドトリップごとにフェッチされる行数の積に設定することで、RowSize
プロパティに応じた値に設定できます。
たとえば、FetchSize
をRowSize
* 10に設定すると、OracleDataReader
オブジェクトでは、データベース・ラウンドトリップごとに10行のみが強制的にフェッチされます。各列のデータ長によってRowSize
が変わることはありません。RowSize
は、SELECT
文が実行されるデータベース表のメタデータ情報から正確に決定されます。
RowSize
プロパティを使用すると、次の項で説明するように、設計時または実行時にFetchSize
プロパティを設定できます。
3.10.4.3.1 レジストリ内のFetchSize値の設定
HKLM\Software\Oracle\ODP.NET\
version
\FetchSize
レジストリ・エントリは、特定のバージョンのODP.NETを使用するすべてのアプリケーションに対するデフォルトの結果セットのフェッチ・サイズをバイト単位で指定するように設定できます。または、アプリケーション構成ファイルまたはweb.config
ファイルのFetchSize
属性で、特定のアプリケーションに対するデフォルト値を指定できます。デフォルトのフェッチ・サイズは131072バイトです。この値は、実行時にアプリケーションのFetchSize
プロパティをOracleCommand
またはOracleDataReader
に対してプログラムで設定することによって無視できます。
3.10.4.3.2 設計時のFetchSize値の設定
特定のSELECT
文の行サイズが前の実行ですでにわかっている場合、OracleCommand
オブジェクトのFetchSize
値は、設計時に、その行サイズとアプリケーションがデータベース・ラウンドトリップごとにフェッチする必要がある行数の積に設定できます。OracleCommand
オブジェクトのFetchSize
値セットは、OracleCommand
オブジェクトでExecuteReader
メソッドを起動したときに作成されたOracleDataReader
オブジェクトにより継承されます。OracleCommand
オブジェクトでFetchSize
値を設定するのではなく、OracleDataReader
オブジェクトで直接FetchSize
値を設定することもできます。いずれの場合にも、実行時にRowSize
プロパティ値にアクセスしなくても、FetchSize
は設計時に設定されます。
3.10.4.3.3 実行時のFetchSize値の設定
設計時に行サイズがわからないアプリケーションでは、OracleCommand
オブジェクトのRowSize
プロパティを使用して、OracleDataReader
オブジェクトのFetchSize
プロパティを設定できます。RowSize
プロパティは、行のサイズに基づいて、動的な方法でFetchSize
プロパティを設定します。
OracleCommand
オブジェクトでExecuteReader
メソッドを起動してOracleDataReader
オブジェクトを取得した後に、RowSize
プロパティが行のサイズ(バイト)とともに移入されます。RowSize
プロパティを使用することで、アプリケーションは、OracleDataReader
オブジェクトのFetchSize
プロパティを、RowSize
プロパティ値とアプリケーションがデータベース・ラウンドトリップごとにフェッチする必要がある行数の積に動的に設定できます。この使用例では、実行時にRowSize
プロパティにアクセスすることでFetchSize
が設定されます。