ヘッダーをスキップ

Oracle® Data Provider for .NET開発者ガイド
リリース9.2.0.4

部品番号 B13807-01
Go To Table Of Contents
目次
Go To Index
索引

Go to previous page Go to next page

3
Oracle Data Provider for .NETの機能

この章では、Oracle Data Provider for .NETのプロバイダ固有の機能と、これらの機能を使用して.NETアプリケーションを開発する方法について説明します。

この章の項目は次のとおりです。

Oracleデータベース・サーバーへの接続

この項では、次のようなOracleConnectionプロバイダ固有の機能について説明します。

接続文字列属性

表 3-1に、サポートされる接続文字列属性をリストします。

表3-1 サポートされる接続文字列属性
接続文字列属性 デフォルト値 説明

Connection Lifetime

0

接続の最長存続時間(秒)。

Connection Timeout

15

プールから空いている接続を待機する最長時間(秒)。

Data Source

空の文字列

接続先のデータベースを識別するOracle Netサービス名。

DBA Privilege

空の文字列

管理権限: SYSDBAまたはSYSOPER

Decr Pool Size

1

確立されているが使用されていない接続の数が多すぎる場合にクローズされる接続の数を制御します。

Enlist

true

分散トランザクション内にサービス・コンポーネントを自動的に登録することを可能または不可にします。

Incr Pool Size

5

プール内のすべての接続が使用されている場合に確立される接続の数を制御します。

Max Pool Size

100

プール内の最大接続数。

Min Pool Size

1

プール内の最小接続数。

Password

空の文字列

User Idで指定されたユーザーのパスワード。

Persist Security Info

false

接続文字列内のパスワード検索を有効または無効にします。

Pooling

true

接続プーリングを有効または無効にします。

Proxy User Id

空の文字列

プロキシ・ユーザーのユーザー名。

Proxy Password

空の文字列

プロキシ・ユーザーのパスワード。

User Id

空の文字列

Oracleユーザー名。

次の例では、接続文字列属性を使用してOracleデータベース・サーバーに接続しています。

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
con.Open();
...

関連項目:

接続属性の詳細は、「ConnectionString」を参照してください。

接続プーリング

ODP.NET接続プーリングを有効および無効にするには、Pooling接続文字列属性を使用します。デフォルトでは、接続プーリングは有効です。接続プーリング・サービスの動作を制御するConnectionString属性は、次のとおりです。

接続プーリングの例

次のコードでは、接続プーリングに関連付けられたConnectionString属性を使用して接続をオープンします。

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;" +
         "Min Pool Size=10;Connection Lifetime=120;Connection Timeout=60;" +
         "Incr Pool Size=5; Decr Pool Size=2";
con.Open();
...

接続プーリングが有効な場合(デフォルト)、OracleConnectionオブジェクトのOpenメソッドとCloseメソッドにより、暗黙的に接続プーリング・サービスが使用されます。上のコードでは、Openのコールによって接続プーリング・サービスが使用されます。この接続プーリング・サービスにより、アプリケーションに接続が返されます。

接続プールは、接続プーリング・サービスによって、ConnectionStringをプールを一意に識別するためのシグネチャとして使用して作成されます。

ConnectionStringの属性値と完全に一致するプールがない場合、新しい接続プールが接続プーリング・サービスによって作成されます。要求されたシグネチャのプールが存在する場合、そのプールからアプリケーションへ接続が返されます。

接続プールが作成される際、接続プーリング・サービスでは、まずConnectionStringMin Pool Size属性で定義されている数の接続が作成されます。接続プールに対して、接続プーリング・サービスによってこの接続数が常に保たれます。

これらの接続は、プール内で使用可能な状態となっているか、アプリケーションで使用されているかのどちらかです。

ConnectionStringIncr Pool Size属性によって、接続プール内で追加の接続が必要な場合に接続プーリング・サービスにより作成される新規の接続の数が定義されます。

アプリケーションにより接続がクローズされると、接続プーリング・サービスにより、接続の存続期間がConnection Lifetime属性を超えていないかどうかが判断されます。この値を超えている場合、接続プーリング・サービスにより接続がクローズされます。超えていない場合、接続は接続プールに戻ります。接続プーリング・サービスによりConnection Lifetimeが強制されるのは、接続が接続プールに戻ろうとするときのみです。

ConnectionStringMax Pool Size属性によって、接続プールの最大接続数が設定されます。新しい接続が要求されたが使用可能な接続がなく、Max Pool Sizeの値に達している場合、接続プーリング・サービスは、Connection Timeoutで定義されている時間待機します。Connection Timeoutを経過した後もプール内に使用可能な接続がない場合、接続プーリング・サービスによって、接続要求が時間切れとなったことを示す例外が呼び出されます。

接続プーリング・サービスにより、接続は、使用されていない場合クローズされます。接続は3分ごとにクローズされます。ConnectionStringDecr Pool Size属性によって、1回の実行でクローズできる最大接続数が接続プーリング・サービスに指定されます。

オペレーティング・システム認証

Oracleデータベース・サーバーでは、データベース・ユーザーの認証にWindowsユーザー・ログイン資格証明を使用できます。Windowsユーザー・ログイン資格証明を使用して接続をオープンするには、ConnectionString属性のUser Id/に設定する必要があります。Passwordが指定されている場合、この値は無視されます。

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=/;Data Source=oracle;";
con.Open();
...

関連資料:

Windowsユーザー・ログイン資格証明を使用するデータベース・ユーザーを認証するようにOracleを設定する方法の詳細は、『Oracle9iセキュリティおよびネットワーク統合ガイド』を参照してください。

特権接続

Oracleでは、データベース管理者はSYSDBA権限またはSYSOPER権限のいずれかを使用してOracleデータベース・サーバーに接続できます。これは、ConnectionStringDBA Privilege属性を介して行われます。

次の例では、SYSDBAとしてSYS/SYSに接続しています。

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=SYS;Password=SYS;" +
    "DBA Privilege=SYSDBA;Data Source=oracle;";
con.Open();
...

関連項目:

データベースでの特権接続の詳細は、「DBA Privilege」を参照してください。

パスワードの期限切れ

Oracleでは、ユーザーのパスワードを期限切れにできます。ODP.NETでは、新しいパスワードで接続をオープンする新規メソッドOpenWithNewPasswordによって、アプリケーションはパスワードの期限切れに対応できます。

次のコードでは、新規パスワードpantherで接続するために、OracleConnectionOpenWithNewPasswordメソッドを使用しています。

// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
//  Here the con.Open() fails if the password has expired.
//  An application catches this and attempts to reconnect with a new password
//  of "panther". The initial connection string must remain intact.

try {
con.Open();
}
catch {
con.OpenWithNewPassword("panther");
}
...


注意:

OpenWithNewPasswordを使用するのはユーザー・パスワードの期限が切れた場合のみとし、パスワードを変更する目的では使用しないでください。


関連項目:

パスワードが期限切れになった後の接続の詳細は、「OpenWithNewPassword」を参照してください。

プロキシ認証

Oracleでは、中間層サーバーを安全な方法でプロキシ・クライアントに接続できます。

中間層環境の場合、プロキシ認証により、すべての層においてクライアントの識別情報と権限が保持され、クライアントにかわって実行された処理が監査されることで、中間層アプリケーションのセキュリティの制御が可能になります。プロキシ認証では、Webアプリケーションを使用するユーザーの識別情報を、そのアプリケーション経由でデータベース・サーバーへ渡すことができます。

ODP.NETでは、ConnectionStringプロパティのProxy User Id属性とProxy Password属性によって、クライアント・パスワードの有無にかかわらずプロキシ認証をサポートします。

// C#
...
OracleConnection con = new OracleConnection();
// Connecting using proxy authentication
con.ConnectionString = "User Id=customer;Password=lion;" +
     "Data Source=oracle;Proxy User Id=appserver;Proxy Password=eagle; ";
con.Open();
...

関連資料:

  • プロキシ・ユーザーを使用した中間層サーバーの設計方法の詳細は、『Oracle9iアプリケーション開発者ガイド - 基礎編』を参照してください。

  • ALTER USERのプロキシ句の説明および構文は、『Oracle9i SQLリファレンス』を参照してください。

  • 『Oracle9iデータベース管理者ガイド』の複数層環境での監査に関する項を参照してください。

透過的アプリケーション・フェイルオーバー(TAF)コールバック・サポート

透過的アプリケーション・フェイルオーバー(TAF)は、高可用性を提供するOracleの機能です。

TAFを使用すると、アプリケーション接続に失敗した場合、自動的にデータベースに再接続されます。アクティブなトランザクションはロールバックされますが、別のノードを経由して行われた新しいデータベース接続は元の接続と同じになります。これは、接続がどのように失敗したかにかかわらず同じです。

TAFを使用した場合、アプリケーションにサービスを提供しているインスタンスがあるかぎり、クライアントでは接続障害は通知されません。データベース管理者は、どのインスタンスでどのアプリケーションが実行されるかを制御し、アプリケーションごとにフェイルオーバー順序を作成します。

フェイルオーバーによる遅延の発生を想定し、TAFコールバックによってアプリケーションに通知することもできます。ODP.NETでは、OracleConnectionオブジェクトのFailoverイベントを介してTAFコールバックをサポートしています。このイベントにより、フェイルオーバーの発生をアプリケーションに通知できます。TAFコールバックを受け取るには、イベント・ハンドラ関数がFailoverイベントに登録されている必要があります。

フェイルオーバーが発生すると、Failoverイベントが呼び出され、別のOracleインスタンスへの接続を再確立する過程で、登録されているイベント・ハンドラが数回起動されます。

イベント・ハンドラの最初のコールは、Oracleデータベースにより最初にインスタンス接続障害が検出されたときに行われます。これによって、アプリケーションは、フェイルオーバーに遅延が発生してもそれに応じて機能します。

フェイルオーバーが成功した場合、接続が再確立されて使用可能になった時点でFailoverイベントが再び呼び出されます。このとき、アプリケーションではOracleGlobalizationセッション設定が再同期化され、フェイルオーバーが行われたことをアプリケーション・ユーザーに通知できます。

フェイルオーバーが失敗した場合、フェイルオーバーが行われなかったことをアプリケーションに通知するためにFailoverイベントが呼び出されます。

アプリケーションでは、イベント・ハンドラに渡されるOracleFailoverEventArgsをチェックすることによって、フェイルオーバーが成功したかどうかを判断できます。

次のコード例では、OnFailoverという名前のイベント・ハンドラ・メソッドを登録します。


// C#
...
OracleConnection con = new OracleConnection();
con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;";
con.Open();
con.Failover += new OracleFailoverEventHandler(OnFailover);
...

Failoverイベントにより起動されるイベント・ハンドラは、1つのみです。複数のFailoverイベント・ハンドラがFailoverイベントに登録されている場合、最後に登録されたイベント・ハンドラのみ起動されます。


注意:

分散トランザクションは、フェイルオーバーが有効な環境ではサポートされません。


関連資料:

ODP.NET型の概要

ODP.NET型は、構造体またはクラスとしてOracle固有の型を表します。ODP.NET型の構造体は値セマンティクスに従い、ODP.NET型のクラスは参照セマンティクスに従います。.NETアプリケーション内では、.NET型よりもODP.NET型の方が、Oracle固有のデータをより安全かつ効率的に取得できます。たとえば、OracleDecimalは最大38精度を保持しますが、.NETのDecimalは最大28精度しか保持しません。

表3-2に、ODP.NETでサポートされるすべてのOracle固有の型と、それに対応するODP.NET型をリストします。3列目には、各ODP.NET型のValueプロパティに対応する.NET Frameworkデータ型をリストします。

表3-2 ODP.NETでサポートされるOracle固有の型
Oracle固有の型 ODP.NET型 .NET Frameworkデータ型

BFILE

OracleBFileクラス

System.Byte[]

BLOB

OracleBlobクラス

System.Byte[]

CHAR

OracleString構造体

System.String

CLOB

OracleClobクラス

System.String

DATE

OracleDate構造体

System.DateTime

INTERVAL DAY TO SECOND

OracleIntervalDS構造体

System.TimeSpan

INTERVAL YEAR TO MONTH

OracleIntervalYM構造体

System.Int64

LONG

OracleString構造体

System.String

LONG RAW

OracleBinary構造体

System.Byte[]

NCLOB

OracleClobクラス

System.String

NCHAR

OracleString構造体

System.String

NUMBER

OracleDecimal構造体

System.Decimal

NVARCHAR2

OracleString構造体

System.String

RAW

OracleBinary構造体

System.Byte[]

REF CURSOR

OracleRefCursorクラス

該当なし

TIMESTAMP

OracleTimeStamp構造体

System.DateTime

TIMESTAMP WITH LOCAL TIME ZONE

OracleTimeStampLTZ構造体

System.DateTime

TIMESTAMP WITH TIME ZONE

OracleTimeStampTZ構造体

System.DateTime

UROWID

OracleString構造体

System.String

VARCHAR2

OracleString構造体

System.String

XMLType

OracleXmlTypeクラス

System.String

OracleDataReaderからのデータの取得

OracleCommandオブジェクトのExecuteReaderメソッドにより、読取り専用で、順方向のみの結果セットであるOracleDataReaderオブジェクトが返されます。

この項では、OracleDataReaderに関する次の情報を示します。

型指定のOracleDataReaderアクセッサ

OracleDataReaderでは、次の2種類の型指定のアクセッサが提供されます。

.NET型アクセッサ

表3-3に、ODP.NETでサポートされているすべてのOracle固有のデータベース型と、そのOracle固有の型を最も適切に表す対応する.NET型をリストします。3列目は、.NET型として取得するOracle固有の型に対して起動できる有効な型指定のアクセッサを示しています。列に対して無効な型指定のアクセッサが使用されると、InvalidCastExceptionがスローされます。Oracle固有のデータ型は、データベースのバージョンによって異なります。このため、一部のデータ型は旧バージョンのOracleでは使用できません。

関連項目:

OracleDataAdapterクラス

表3-3 .NET型アクセッサ
Oracle固有のデータ型 .NET型 型指定のアクセッサ

BFILE

System.Byte[ ]

GetBytes

BLOB

System.Byte[ ]

GetBytes

CHAR

System.String

GetString

GetChars

CLOB

System.String

GetString

GetChars

DATE

System.DateTime

GetDateTime

INTERVAL (DS)

System.Interval

GetTimeSpan

INTERVAL (YM)

System.Interval

GetTimeSpan

LONG

System.String

GetString

GetChars

LONG RAW

System.Byte[ ]

GetBytes

NCHAR

System.String

GetString

GetChars

NCLOB

System.String

GetString

GetChars

NUMBER

System.Decimal

GetDecimal

NVARCHAR2

System.String

GetString

GetChars

RAW

System.Byte[ ]

GetBytes

ROWID

System.String

GetString

GetChars

TIMESTAMP

System.TimeStamp

GetTimeStamp

TIMESTAMP WITH LOCAL TIME ZONE

System.TimeStamp

GetTimeStamp

TIMESTAMP WITH TIME ZONE

System.TimeStamp

GetTimeStamp

UROWID

System.String

GetString

GetChars

VARCHAR2

System.String

GetString

GetChars

XMLType

System.String

System.Xml.XmlReader

GetString

GetXmlReader

ODP.NET型アクセッサ

ODP.NETは、Oracle固有のデータ型を表すプロバイダ固有の型を公開します。これらのODP.NET型は、対応する.NET型では実現できないパフォーマンスと機能を提供することがあります。ODP.NET型は、それぞれの型指定のアクセッサを呼び出してOracleDataReaderから取得します。

関連項目:

すべてのODP.NET型のリストは、「ODP.NET型の概要」を参照してください。

表3-4に、ODP.NETでOracle固有の型に対応するODP.NET型を取得する際に使用される、有効な型アクセッサをリストします。

表3-4 ODP.NET型アクセッサ
Oracle固有のデータベース型 ODP.NET型 型指定のアクセッサ

BFILE

OracleBFile

GetOracleBFile

BLOB

OracleBlob

OracleBlob

OracleBinary

GetOracleBlob

GetOracleBlobForUpdate

GetOracleBinary

CHAR

OracleString

GetOracleString

CLOB

OracleClob

OracleClob

OracleString

GetOracleClob

GetOracleClobForUpdate

GetOracleString

DATE

OracleDate

GetOracleDate

INTERVAL (DS)

OracleIntervalDS

GetOracleIntervalDS

INTERVAL (YM)

OracleIntervalYM

GetOracleIntervalYM

LONG

OracleString

GetOracleString

LONG RAW

OracleBinary

GetOracleBinary

NCHAR

OracleString

GetOracleString

NCLOB

OracleString

GetOracleString

NUMBER

OracleDecimal

GetOracleDecimal

NVARCHAR2

OracleString

GetOracleString

RAW

OracleBinary

GetOracleBinary

ROWID

OracleString

GetOracleString

TIMESTAMP

OracleTimeStamp

GetOracleTimeStamp

TIMESTAMP WITH LOCAL TIME ZONE

OracleTimeStampLTZ

GetOracleTimeStampLTZ

TIMESTAMP WITH TIME ZONE

OracleTimeStampTZ

GetOracleTimeStampTZ

UROWID

OracleString

GetOracleString

VARCHAR2

OracleString

GetOracleString

XMLType

OracleString

GetOracleString

OracleXmlType

GetOracleXmlType

LONGおよびLONG RAWデータの取得

LONGまたはLONG RAWの列型を含むOracleDataReaderが作成されると、OracleDataReaderを作成したOracleCommandInitialLONGFetchSizeプロパティの値がOracleDataReaderによってチェックされ、その列データをすぐにフェッチする必要があるかどうかが判断されます。

デフォルトでは、InitialLONGFetchSize0に設定されています。OracleCommandInitialLONGFetchSizeプロパティの値が0のままであれば、LONGまたはLONG RAWデータ全体の取得が、アプリケーションによってデータが明示的に要求されるまで延期されます。InitialLONGFetchSizeプロパティがゼロ以外の値に設定されている場合、その値の文字数またはバイト数までLONGまたはLONG RAWデータが即座にフェッチされます。

ODP.NETでは、CommandBehavior.SequentialAccessはサポートされません。このため、LONGおよびLONG RAWデータは、ランダムにフェッチできます。

InitialLONGFetchSizeのバイト数または文字数を超えるデータを取得するためには、選択リストに次のいずれかが含まれている必要があります。

要求されたデータは、適切な型指定のアクセッサ・メソッド(LONGの場合はGetOracleStringまたはGetStringLONG RAWの場合はGetOracleBinaryまたはGetBytes)がOracleDataReaderオブジェクトでコールされると、データベースからフェッチされます。

非遅延モードでデータをフェッチする場合、または選択リストの列に主キー列、ROWIDまたは一意な列群のいずれもない場合は、OracleCommandオブジェクトのInitialLONGFetchSizeプロパティのサイズを、取得するバイトまたは文字数以上に設定してください。

LOBデータの取得

LOBの列型を含むOracleDataReaderが作成されると、OracleDataReaderを作成したOracleCommandInitialLOBFetchSizeプロパティの値がOracleDataReaderによってチェックされ、LOBの列データをすぐにフェッチする必要があるかどうかが判断されます。デフォルトでは、InitialLOBFetchSize0に設定されています。OracleCommandInitialLOBFetchSizeプロパティの値が0のままであれば、LOBデータ全体の取得が、アプリケーションによってデータが明示的に要求されるまで延期されます。InitialLOBFetchSizeプロパティがゼロ以外の値に設定されている場合、その値の文字数またはバイト数までLOBデータが即座にフェッチされます。

デフォルトのままInitialLOBFetchSizeプロパティが0の場合、OracleDataReaderGetOracleBlob()およびGetOracleClob()を起動してOracleBlobおよびOracleClobオブジェクトを取得できます。ただしInitialLOBFetchSizeがゼロ以外の値に設定されている場合、GetOracleBlob()およびGetOracleClob()メソッドは無効です。その場合には、GetBytes()およびGetChars()をそれぞれ使用してBLOBおよびCLOBデータをフェッチする必要があります。

InitialLOBFetchSizeをデフォルト以外の値に設定すると、特定のケースでパフォーマンスを向上させることができます。InitialLOBFetchSizeGetBytes()およびGetChars()と一緒に使用すると、OracleBlobおよびOracleClobオブジェクトを使用してLOBデータを取得する場合よりも高いパフォーマンスを得られることがあります。OracleDataReaderからOracleBlobおよびOracleClobオブジェクトを取得する必要のないアプリケーションで、LOB列データがそれほど大きくない場合がこれに該当します。InitialLOBFetchSizeは、問合せで返されるLOB列データのサイズがすべての行でほぼ同じ場合、特に便利です。

一般にInitialLOBFetchSizeは、問合せで返される行のうち、8割を超える行のLOBデータのサイズよりも大きな値に設定することをお薦めします。たとえば、8割の行でLOBデータのサイズが1KBよりも小さく、2割の行で1MBよりも大きい場合には、InitialLOBFetchSizeを1KBに設定します。

ODP.NETでは、CommandBehavior.SequentialAccessはサポートされません。このため、LOBデータはランダムにフェッチできます。

InitialLOBFetchSizeのバイト数または文字数を超えるデータを取得するためには、選択リストに次のいずれかが含まれている必要があります。

要求されたデータは、適切な型指定のアクセッサ・メソッドがOracleDataReaderオブジェクトでコールされると、データベースからフェッチされます。InitialLOBFetchSiz0に設定されている場合には、主キー列は必要ありません。

非遅延モードでデータをフェッチする場合、または選択リストの列に主キー列、ROWIDまたは一意な列群のいずれもない場合は、OracleCommandオブジェクトのInitialLOBFetchSizeプロパティのサイズを、取得するバイト数または文字数以上に設定してください。

1回のサーバー・ラウンドトリップでフェッチされる行数の制御

アプリケーションのパフォーマンスは、アプリケーションがフェッチしなければならない行数と、それらの取得に必要なデータベース・ラウンドトリップの数によって決まります。

FetchSizeの使用

FetchSizeプロパティは、1回のサーバー・ラウンドトリップでフェッチされたデータをキャッシュするためにODP.NETで割り当てられるメモリーの合計サイズをバイトで表します。

FetchSizeプロパティは、状況に応じてOracleCommandまたはOracleDataReaderのどちらにも設定できます。また、OracleCommandFetchSizeプロパティはOracleDataReaderに継承されますが、これは変更可能です。

FetchSizeプロパティがOracleCommandに設定されている場合、新しく作成されるOracleDataReaderにはOracleCommandFetchSizeプロパティが継承されます。継承されたFetchSizeはそのままにすることも、変更してオーバーライドすることもできます。OracleDataReaderオブジェクトのFetchSizeプロパティは、FetchSizeで指定されたメモリーを割り当てる最初のReadメソッドの起動前に変更します。その後のデータベースからのフェッチでは、すべてそのOracleDataReaderに割り当てられたキャッシュが使用されます。したがって、最初のReadメソッドが起動された後でFetchSizeを変更しても効果はありません。

FetchSizeの調整

FetchSizeプロパティを調整すれば、メモリーの使用と1回のサーバー・ラウンドトリップでフェッチされる行数をアプリケーションで制御し、パフォーマンスを改善することができます。たとえばある問合せで100行が返され、各行が1024バイトを使用する場合、FetchSizeを102400に設定すると、その100行をフェッチするのに必要なサーバー・ラウンドトリップは1回のみになります。同じ問合せで、FetchSizeを10240に設定した場合、100行を取得するのに必要なサーバー・ラウンドトリップは10回になります。結果セットからすべての行をフェッチする必要のあるアプリケーションの場合、最初の設定の方が処理速度は速くなります。ただし、結果セットの最初の10行だけを必要とするアプリケーションでは、100行ではなく10行だけをフェッチする2つ目の設定の方が高いパフォーマンスを得ることができます。

RowSizeプロパティの使用

OracleCommandオブジェクトのRowSizeプロパティには、SELECT文の実行後に行サイズ(バイト)が移入されます。FetchSizeプロパティは、このRowSizeプロパティに各サーバー・ラウンドトリップでフェッチする行数を掛けた値に設定できます。

たとえば、FetchSizeRowSize×10に設定すると、OracleDataReaderは各サーバー・ラウンドトリップごとにちょうど10行をフェッチします。RowSizeは、個々の列のデータ長によっては変化しません。RowSizeは、SELECTが実行されるデータベース表のメタデータ情報から厳密に決定されます。

RowSizeプロパティを使用して、設計時または実行時にFetchSize設定できます。それぞれのケースについて次に説明します。

設計時におけるFetchSize値の設定

特定のSELECT文に対する行サイズが過去の実行結果から明らかな場合、OracleCommandFetchSizeを、その行サイズとアプリケーションが1回のサーバー・ラウンドトリップでフェッチする行数を掛けた値に設計時に設定できます。OracleCommandオブジェクトに設定されたFetchSizeの値は、OracleCommandへのExecuteReaderメソッドの起動によって作成されるOracleDataReaderに継承されます。OracleCommandオブジェクトにFetchSizeを設定するかわりに、OracleDataReaderに直接FetchSizeを設定することもできます。どちらの場合も、FetchSizeは設計時に設定され、実行時のRowSizeプロパティにはアクセスしません。

実行時におけるFetchSize値の設定

設計時に行サイズが明らかでないアプリケーションでは、OracleCommandオブジェクトのRowSizeプロパティを使用してOracleDataReaderオブジェクトのFetchSizeプロパティを設定できます。RowSizeプロパティにより、行のサイズに基づいてFetchSizeプロパティを動的に設定することができます。

OracleCommandExecuteReaderメソッドが起動されてOracleDataReaderオブジェクトが取得されると、RowSizeプロパティに行のサイズ(バイト)が移入されます。このRowSizeプロパティを使用することにより、OracleDataReaderFetchSizeプロパティを、RowSizeプロパティの値に1回のサーバー・ラウンドトリップでフェッチする行数を掛けた値に動的に設定することができます。この場合、FetchSizeは実行時のRowSizeプロパティにアクセスして設定されます。

OracleCommandオブジェクト

OracleCommandオブジェクトは、Oracleデータベース上で実行されるSQL文またはストアド・プロシージャを表します。

この項では、次の項目について説明します。

トランザクション

Oracleデータベースでは、接続のコンテキストでのみトランザクションが開始されます。いったんトランザクションが開始されると、その接続での連続するすべてのコマンドはそのトランザクションのコンテキスト内で実行されます。トランザクションはOracleConnectionオブジェクトでのみ開始でき、OracleCommandオブジェクトに対する読取り専用のTransactionプロパティは、OracleConnectionオブジェクトによって暗黙的に設定されます。したがって、アプリケーションではTransactionプロパティを設定できず、またその必要もありません。

パラメータ・バインド

ODP.NETでは、アプリケーションはデータを.NET Framework型またはODP.NET型として取得できます。

データがどちらの形で取得されるかは、アプリケーションでOUTパラメータがOracleParameterDbTypeプロパティ(.NET型)またはOracleDbTypeプロパティ(ODP.NET型)のどちらに設定されるかによって決まります。

たとえば、出力パラメータがDbType.Stringとしてバインドされている場合、出力データは.NET Stringとして返されます。逆にパラメータがOracleDbType.Charとしてバインドされている場合、出力データはOracleString型として返されます。

OracleParameterDbTypeが設定されている場合、OracleParameterOracleDbTypeはそれに応じて変更されます。またその逆も同様です。最後に設定されたパラメータが優先されます。

また、アプリケーションでは単にデータをバインドし、パラメータ値の.NET型からDbTypeOracleDbTypeの両方をODP.NETに推論させることもできます。

ODP.NETでは、次のOracleCommandメソッドの実行により、InputOutputOutputおよびReturnValueパラメータにOracleデータが移入されます。

アプリケーションで出力パラメータの値をバインドする必要はありません。ODP.NETにより値オブジェクトが作成され、OracleParameterValueプロパティにそのオブジェクトが移入されます。

この項では、次の項目について説明します。

OracleDbType列挙体

OracleDbType列挙値は、OracleParameterOracleDbTypeを明示的に指定するために使用されます。

表3-5に、すべてのOracleDbType列挙値をリストし、各値について説明します。

表3-5 OracleDbType列挙値
メンバー名 説明

BFile

OracleのBFILE

Blob

OracleのBLOB

Byte

byte

Char

OracleのCHAR

Clob

OracleのCLOB

Date

OracleのDATE

Decimal

OracleのNUMBER

Double

8バイトのFLOAT

Int16

2バイトのINTEGER

Int32

4バイトのINTEGER

Int64

8バイトのINTEGER

IntervalDS

OracleのINTERVAL DAY TO SECOND

IntervalYM

OracleのINTERVAL YEAR TO MONTH

Long

OracleのLONG

LongRaw

OracleのLONG RAW

NChar

OracleのNCHAR

NClob

OracleのNCLOB

NVarchar2

OracleのNVARCHAR2

Raw

OracleのRAW

RefCursor

OracleのREF CURSOR

Single

4バイトのFLOAT

TimeStamp

OracleのTIMESTAMP

TimeStampLTZ

OracleのTIMESTAMP WITH LOCAL TIME ZONE

TimeStampTZ

OracleのTIMESTAMP WITH TIME ZONE

Varchar2

OracleのVARCHAR2

XmlType

OracleのXMLType

DbType、OracleDbTypeおよび.NET型の推論

この項では、OracleParameterクラス内のSystem.Data.DbTypeOracleDbTypeおよびValueプロパティからの推論について説明します。

OracleParameterクラス内では、DbTypeOracleDbTypeおよびValueプロパティはリンクされています。このいずれかのプロパティの値を指定すると、1つ以上の他のプロパティの値が推論されます。

OracleDbTypeからのDbTypeの推論

OracleParameterクラス内で、OracleDbTypeの値を指定すると、表3-6に示されたDbTypeの値が推論されます。

表3-6 OracleDbTypeからのSystem.Data.DbTypeの推論
OracleDbType System.Data.DbType

BFile

Object

Blob

Object

Byte

Byte

Char

StringFixedLength

Clob

Object

Date

Date

Decimal

Decimal

Double

Double

Int16

Int16

Int32

Int32

Int64

Int64

IntervalDS

TimeSpan

IntervalYM

Int64

Long

String

LongRaw

Binary

NChar

StringFixedLength

NClob

Object

NVarchar2

String

Raw

Binary

RefCursor

Object

Single

Single

TimeStamp

DateTime

TimeStampLTZ

DateTime

TimeStampTZ

DateTime

Varchar2

String

XmlType

String

DbTypeからのOracleDbTypeの推論

OracleParameterクラス内で、DbTypeの値を指定すると、表3-7に示されたOracleDbTypeの値が推論されます。

表3-7 DbTypeからのOracleDbTypeの推論
System.Data.DbType OracleDbType

Binary

Raw

Boolean

サポートなし

Byte

Byte

Currency

サポートなし

Date

Date

DateTime

TimeStamp

Decimal

Decimal

Double

Double

Guid

サポートなし

Int16

Int16

Int32

Int32

Int64

Int64

Object

サポートなし

Sbyte

サポートなし

Single

Single

String

Varchar2

StringFixedLength

Char

Time

TimeStamp

UInt16

サポートなし

UInt32

サポートなし

Uint64

サポートなし

VarNumeric

サポートなし

ValueからのDbTypeおよびOracleDbTypeの推論

OracleParameterクラス内で、Valueは、あらゆる.NET Frameworkデータ型またはODP.NET型にできるオブジェクト型です。OracleParameterオブジェクト内のOracleDbTypeおよびDbTypeが指定されていない場合、Valueプロパティの型からOracleDbTypeが推論されます。

表3-8に、Valueの型がいずれかの.NET Frameworkデータ型である場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。

表3-8 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの推論
Value(.NETデータ型) System.Data.DbType OracleDbType

Byte

Byte

Byte

Byte[]

Binary

Raw

Char / Char []

String

Varchar2

DateTime

DateTime

TimeStamp

Decimal

Decimal

Decimal

Double

Double

Double

Float

Single

Single

Int16

Int16

Int16

Int32

Int32

Int32

Int64

Int64

Int64

Single

Single

Single

String

String

Varchar2

TimeSpan

TimeSpan

IntervalDS


注意:

これ以外の.NET Frameworkデータ型からのDbTypeおよびOracleDbTypeの推論はサポートされていないため、DbTypeまたはOracleDbTypeを指定せずにOracleParameterの値としてそれ以外の.NET Frameworkデータ型を使用すると、例外が呼び出されます。


表3-9に、Valueの型がいずれかのOracle.DataAccess.Typesである場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。

表3-9 Value(ODP.NETデータ型)からのDbTypeおよびOracleDbTypeの推論
Value(Oracle.DataAccess.Types) System.Data.DbType OracleDbType

OracleBFile

Object

BFile

OracleBinary

Binary

Raw

OracleBlob

Object

Blob

OracleClob

Object

Clob

OracleDate

Date

Date

OracleDecimal

Decimal

Decimal

OracleIntervalDS

Object

IntervalDS

OracleIntervalYM

Int64

IntervalYM

OracleRefCursor

Object

RefCursor

OracleString

String

Varchar2

OracleTimeStamp

DateTime

TimeStamp

OracleTimeStampLTZ

DateTime

TimeStampLTZ

OracleTimeStampTZ

DateTime

TimeStampTZ

OracleXmlType

String

XmlType

PL/SQL連想配列

ODP.NETは、PL/SQL連想配列(以前はPL/SQL索引付き表と呼ばれていた)のバインドをサポートします。

アプリケーションで、OracleParameterをPL/SQLストアド・プロシージャにPL/SQL連想配列としてバインドすることができます。この機能では、次のOracleParameterプロパティを使用します。

コード例

この例は、3つのOracleParameterオブジェクトをPL/SQL連想配列としてバインドしています。具体的には、Param1Inパラメータとして、Param2InputOutputパラメータとして、Param3Outputパラメータとしてバインドします。

PL/SQLパッケージ: My Pack

CREATE PACKAGE MYPACK AS
TYPE AssocArrayVarchar2_t is table of VARCHAR(20) index by BINARY_INTEGER;
PROCEDURE TestVarchar2(
    Param1 IN     AssocArrayVarchar2_t,
    Param2 IN OUT AssocArrayVarchar2_t,
    Param3 OUT    AssocArrayVarchar2_t);
END MYPACK;

PL/SQLパッケージ・ボディ: My Pack

CREATE PACKAGE BODY MYPACK AS
PROCEDURE TestVarchar2(
    Param1 IN     AssocArrayVarchar2_t,
    Param2 IN OUT AssocArrayVarchar2_t,
    Param3 OUT    AssocArrayVarchar2_t)
    IS
    i integer;
    BEGIN
      -- copy a few elements from y to z
      Param3(1) := Param2(1);
      Param3(2) := NULL;
      Param3(3) := Param2(3);

      -- copy all elements from x to y
      Param2(1) := Param1(1);
      Param2(2) := Param1(2);
      Param2(3) := Param1(3);

      FOR i IN 1..3 LOOP
        insert into T1 values(i, Param2(i));
      END LOOP;

      FOR i IN 1..3 LOOP
        select COL2 into Param2(i) from T2 where COL1 = i;
      END LOOP;
    END TestVarchar2;
END MYPACK;

ODP.NETの例


public void BindAssocArray()
{
...

      OracleCommand cmd = new OracleCommand(
        "begin MyPack.TestVarchar2(:1, :2, :3); end;", con);

      OracleParameter Param1 = cmd.Parameters.Add(...);
      OracleParameter Param2 = cmd.Parameters.Add(...);
      OracleParameter Param3 = cmd.Parameters.Add(...);

      Param1.Direction = ParameterDirection.Input;
      Param2.Direction = ParameterDirection.InputOutput;
      Param3.Direction = ParameterDirection.Output;

      // Specify that we are binding PL/SQL Associative Array
      Param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
      Param2.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
      Param3.CollectionType = OracleCollectionType.PLSQLAssociativeArray;

      // Setup the values for PL/SQL Associative Array
      Param1.Value = new string[3]{"First Element",
                                   "Second Element ",
                                   "Third Element ",
      Param2.Value = new string[3]{"First Element",
                                   "Second Element ",
                                   "Third Element ",
      Param3.Value = null;

      // Specify the maximum number of elements in the PL/SQL Associative Array
      Param1.Size = 3;
      Param2.Size = 3;
      Param3.Size = 3;

      // Setup the ArrayBindSize for Param1
      Param1.ArrayBindSize = new int[3]{13, 14, 13};

      // Setup the ArrayBindStatus for Param1
      Param1.ArrayBindStatus = new OracleParameterStatus[3]{
        OracleParameterStatus.Success,
        OracleParameterStatus.Success,
        OracleParameterStatus.Success};

      // Setup the ArrayBindSize for Param2
      Param2.ArrayBindSize = new int[3]{20, 20, 20};

      // Setup the ArrayBindSize for Param3
      Param3.ArrayBindSize = new int[3]{20, 20, 20};

      // execute the cmd
      cmd.ExecuteNonQuery();

      //print out the parameter's values
      ......
    }

配列バインド

配列バインド機能により、アプリケーションはOracleParameterクラスを使用して型の配列をバインドできます。配列バインド機能を使用すると、アプリケーションは1回のデータベース・ラウンドトリップで複数の行を表に挿入できます。

次のコード例では、1回のデータベース・ラウンドトリップで3つの行をDept表に挿入します。OracleCommandArrayBindCountプロパティにより、文の実行時に使用される配列の要素数が定義されます。

// C#
...
// Create an array of values that need to be inserted
int[] myArrayDeptNo = new int[3]{10, 20, 30};

// Set the command text on an OracleCommand object
cmd.CommandText = "insert into dept(deptno) values (:deptno)";
// Set the ArrayBindCount to indicate the number of values
cmd.ArrayBindCount = 3;

// Create a parameter for the array operations
OracleParameter prm = new OracleParameter("deptno", OracleDbType.Int32);
prm.Direction = ParameterDirection.Input;
prm.Value     = myArrayDeptNo;

// Add the parameter to the parameter collection
cmd.Parameters.Add(prm);

// Execute the command
cmd.ExecuteNonQuery();

関連項目:

詳細は、「Value」を参照してください。

OracleParameter配列バインド・プロパティ

OracleParameterオブジェクトでは、配列バインド機能を使用する際の粒度の制御のために2つのプロパティが提供されます。

配列バインドのエラー処理

配列バインドの実行中にエラーが発生した場合、Valueプロパティ内のどの要素がエラーの原因かを判断することは困難です。ODP.NETにはエラーが発生した行を特定する機能があるため、エラーを引き起こした要素をその行の中から簡単に見つけることができます。

配列バインドの実行中にOracleExceptionがスローされると、OracleErrorCollectionに1つ以上のOracleErrorオブジェクトが追加されます。1つ1つのOracleErrorオブジェクトは実行中に発生した個々のエラーを表し、プロバイダ固有のプロパティであるArrayBindIndexが含まれます。ArrayBindIndexにはエラーが発生した行番号が示されます。

コード例

try {
  / An Array Bind execution errors out
}

catch (OracleException e)
{
  Console.WriteLine ("OracleException {0} occured", e.Message);
  for (int i = 0; i < e.Errors.Count; i++)
    Console.WriteLine("Array Bind Error {0} occured at Row Number {1}",
e.Errors[i].Message,
      e.Errors[i].ArrayBindIndex);
}

関連項目:

ArrayBindIndex

OracleParameterStatus列挙型

表3-10に、OracleParameterStatus列挙体の様々な値を示します。

表3-10 OracleParameterStatusのメンバー
メンバー名 説明

Success

入力パラメータの場合、入力値が列に割り当てられたことを示します。

出力パラメータの場合、プロバイダにより完全な値がパラメータに割り当てられたことを示します。

NullFetched

null値が列またはOUTパラメータからフェッチされたことを示します。

NullInsert

null値が列に挿入されることを示します。

Truncation

列からデータをフェッチする際に切捨てが発生したことを示します。

PL/SQL REF CURSORおよびOracleRefCursor

REF CURSORは、OracleのPL/SQL言語におけるデータ型です。これは、Oracleデータベース・サーバーでのカーソルまたは結果セットを表します。OracleRefCursorは、REF CURSOR型に対応するODP.NET型です。

この項では、REF CURSORおよびOracleRefCursorオブジェクトの使用方法に関する次の内容について説明します。

OracleRefCursorの取得

OracleRefCursorオブジェクトに対するコンストラクタはありません。コンストラクタは、PL/SQLストアド・プロシージャ、ストアド・ファンクションまたは無名ブロックからパラメータ値として取得できるだけです。

OracleRefCursorは接続オブジェクトです。OracleRefCursorオブジェクトを返すコマンドの実行に使用される接続は、その存続期間中は必要です。OracleRefCursorに関連付けられた接続がクローズされると、OracleRefCursorは使用できなくなります。

REF CURSORの取得

REF CURSORは、OracleDataReaderDataSetまたはOracleRefCursorとして取得できます。OracleRefCursorオブジェクトとして取得されたREF CURSORは、OracleDataReaderの作成またはREF CURSORからDataSetへの移入に使用できます。REF CURSORにアクセスする際は、必ずOracleDbType.RefCursorとしてバインドします。

REF CURSORからOracleDataReaderへの移入

OracleのREF CURSORは、OracleCommandExecuteReaderメソッドをコールすることにより、OracleDataReaderとして取得できます。OracleDbTypeプロパティが設定された出力パラメータは、OracleDbType.RefCursorにバインドされます。ExecuteReaderのコール後に移入されるOracleDbType.RefCursor型の出力パラメータはありません。

複数の出力REF CURSORパラメータがある場合は、OracleDataReaderNextResultメソッドを使用して次のREF CURSORにアクセスします。OracleDataReaderNextResultメソッドでは、REF CURSORへの順次アクセスを提供します。つまり、一度に1つのREF CURSORにしかアクセスできません。

OracleDataReaderオブジェクトが対応するREF CURSORに対して作成される順序は、パラメータがバインドされる順序によって決まります。PL/SQLストアド・ファンクションによりREF CURSORが返された場合、これが最初のOracleDataReaderになり、すべての出力REF CURSORオブジェクトは、パラメータがバインドされる順序に従います。

REF CURSORからDataSetへの移入

FillメソッドによりDataSetプロパティへの移入が適切に行われるためには、OracleDataAdapterSelectCommandが、OracleDbType.RefCursor型の出力パラメータでバインドされている必要があります。Fillメソッドが正常に実行されると、DataSetREF CURSORを表すDataTableが移入されます。

コマンド実行により複数のREF CURSORが返された場合、DataSetに複数のDataTableが移入されます。

REF CURSORからOracleRefCursorへの移入

1つ以上のREF CURSORを返すコマンドでExecuteNonQueryが起動されると、OracleDbType.RefCursorとしてバインドされているOracleCommandパラメータそれぞれがOracleRefCursorオブジェクトへの参照を取得します。

OracleRefCursorオブジェクトからOracleDataReaderを作成するには、OracleRefCursorオブジェクトからGetDataReaderをコールします。それ以降にGetDataReaderをコールすると、同じOracleDataReaderへの参照が返されます。

DataSetOracleRefCursorオブジェクトを移入する場合、アプリケーションでは、OracleRefCursorオブジェクトをとるOracleDataAdapterFillメソッドをコールできます。

コマンド実行によって複数のREF CURSOROracleRefCursorオブジェクトとして返された場合、アプリケーションでは、OracleDataReaderを作成するか、DataSetに特定のOracleRefCursorオブジェクトを移入するかを選択できます。OracleRefCursorから作成されたすべてのOracleDataReaderまたはDataSetは同時にアクティブになり、任意の順序でアクセスできます。

REF CURSORから取得されたDataSetの更新

REF CURSORは更新可能ではありません。ただし、DataSet内に取得されたデータは更新可能です。このため、OracleDataAdapterでは、データベースにREF CURSORデータの更新をフラッシュするためのカスタムSQL文が必要です。

REF CURSOR更新用のSQLを生成するためにOracleCommandBuilderは使用できません。

REF CURSORに対するExecuteScalarメソッドの動作

ExecuteScalarは、ストアド・ファンクションの戻り値か、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータを返します。このため、REF CURSORがストアド・ファンクションの戻り値でも、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータでもない場合、REF CURSORExecuteScalarに無視されます。

しかし、REF CURSORがストアド・ファンクションの戻り値か、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータである場合は、REF CURSOR内の最初の行の最初の列の値が返されます。

関連資料:

詳細は、『Oracle9iアプリケーション開発者ガイド-ラージ・オブジェクト』を参照してください。

LOBサポート

ODP.NETには、ラージ・オブジェクト・データ型にアクセスおよび操作するための簡単で最適な方法があります。Oracleでは、文字データおよびバイナリ・データのLOBデータ型がサポートされています。

文字データのLOBデータ型
バイナリ・データのLOBデータ型

ODP.NETでは、LOBデータを操作するための、OracleBFileOracleBlobおよびOracleClobというの3つのLOB用オブジェクトが提供されます。

表3-11に、特定のOracle LOB型に使用する適切なODP.NETクラスを示します。

表3-11 ODP.NET LOBオブジェクト
Oracle LOB型 ODP.NET LOBオブジェクト

BFILE

OracleBFileオブジェクト

BLOB

OracleBlobオブジェクト

CLOB

OracleClobオブジェクト

NCLOB

OracleClobオブジェクト

ODP.NET LOBオブジェクトは、OracleDataReaderで適切な型指定のアクセッサをコールして取得するか、または適切なバインド型を使用したコマンド実行で出力パラメータとして取得することができます。

すべてのODP.NET LOBオブジェクトは、.NETのStreamクラスから継承され、汎用Stream操作を可能にします。LOBデータ(BFILEを除く)は、Writeなどのメソッドを使用することによって、ODP.NET LOBオブジェクトを使用した更新が可能になります。読取り/書込み操作が行われる際、データはLOBオブジェクト内にキャッシュされません。このため、ReadまたはWriteが要求されるたびに、サーバー・ラウンドトリップが発生します。OracleClobReadメソッドをオーバーロードし、CLOBからデータを読み込む2つの方法を提供します。バッファとしてbyte[]をとるReadメソッドは、Unicodeバイト配列としてCLOBデータを移入します。バッファとしてchar[]をとるReadメソッドは、Unicode文字を移入します。

OracleBFileオブジェクトで、拡張部分を見つけることもできます。データをOracleBFileオブジェクトから読み込むには、このオブジェクトがOpenFileメソッドを使用して明示的にオープンされている必要があります。すでにオープンされているBFILEをクローズするには、CloseFileメソッドを使用します。

あらゆるODP.NET LOBオブジェクトは接続オブジェクトであり、存続期間中は接続を必要とします。LOBオブジェクトに関連付けられた接続がクローズされると、そのLOBオブジェクトは使用できなくなり、廃棄する必要があります。

ODP.NET LOBオブジェクトが型指定のアクセッサを介してOracleDataReaderから取得された場合、そのConnectionプロパティには、OracleDataReaderで使用されるのと同じOracleConnectionオブジェクトへの参照が設定されます。LOBオブジェクトが出力パラメータとして取得された場合、そのConnectionプロパティは、OracleCommandで使用されるのと同じOracleConnectionプロパティへの参照で設定されます。LOBオブジェクトが、一時LOBを作成するためのODP.NET LOBオブジェクトのコンストラクタを起動することにより取得された場合、Connectionプロパティには、コンストラクタで指定されているOracleConnectionオブジェクトへの参照が設定されます。

ODP.NET LOBオブジェクトのConnectionプロパティは読取り専用であり、その存続期間中は変更できません。また、ODP.NET LOB型オブジェクトは、ODP.NET LOBオブジェクトで参照されるのと同じOracleConnectionのコンテキスト内でのみ使用できます。たとえば、ODP.NET LOBオブジェクトがOracleCommandのパラメータである場合、ODP.NET LOBオブジェクトのConnectionは、OracleCommandと同じ接続を参照している必要があります。そうでない場合、ODP.NETではコマンドの実行時に例外が呼び出されます。

関連資料:

Oracle9i LOBとその使用方法の詳細は、『Oracle9iアプリケーション開発者ガイド-ラージ・オブジェクト』を参照してください。

DataSetを使用したLOBの更新

BFILEおよびBLOBデータはbyte配列としてDataSet内に格納され、CLOBおよびNCLOBデータはstringとして格納されます。他の型と同様に、OracleDataAdapterオブジェクトを使用すると、SQLを自動生成するためにOracleCommandBuilderも使用してLOBデータ変更を埋め込み、更新することができます。

Oracle LOB列に格納できるデータは最大4GBですので注意してください。LOBデータがDataSet内にフェッチされると、DataSetがLOB列に保持できるLOBデータの実際の量は、.NETの文字列型の最大サイズ(2GB)に制限されます。したがって、2GBを超えるLOBデータをフェッチする場合は、データの損失を回避するためにODP.NET LOBオブジェクトを使用する必要があります。

OracleCommandおよびOracleParameterを使用したLOBの更新

LOB列を更新する場合、LOBデータを、SQL文、無名PL/SQLブロックまたはストアド・プロシージャのパラメータとしてバインドできます。パラメータ値は、NET Framework型、ODP.NET型またはODP.NET LOBオブジェクト型として設定できます。たとえば、.NET文字列データをOracle9iデータベース内のLOB列に挿入する場合、そのパラメータをOracleDbType.Varchar2としてバインドできます。値がOracleClobオブジェクトに設定されているパラメータの場合は、パラメータをOracleDbType.Clobとしてバインドする必要があります。

ODP.NET LOBオブジェクトを使用したLOBの更新

OracleのBFILEは更新不可能なので、OracleBFileオブジェクトではBFILE列の更新は許可されません。

ODP.NET LOBオブジェクトを使用してLOBデータを更新するには、次の2つの要件を満たしている必要があります。

  1. LOB列の選択前に、トランザクションが開始されている必要があります。

    OracleTransactionCommitまたはRollbackの起動時にロックを解放できるように、OracleCommandの実行前にこのコマンドのBeginTransactionメソッドを使用してトランザクションが開始されている必要があります。

  2. LOB列が置かれている行は、行単位で、または結果セット全体の一部としてロックされている必要があります。

    1. 結果全体のロック。

      SELECT文の終わりにFOR UPDATE句を追加します。コマンドの実行後、結果セット全体がロックされます。

    2. 行のロック。次の2つのオプションがあります。

      • OracleDataReaderOracleDataReaderの型指定のアクセッサのいずれか(GetOracleClobForUpdateまたはGetOracleBlobForUpdate)を起動して、現在の行をロックしている間にODP.NET LOBオブジェクトを取得します。

        このアプローチでは、OracleDataReaderでロックする行を再選択するためにその行を一意に識別する必要があるため、結果セット内に主キー、一意な列またはROWIDが必要になります。

      • RETURNING句でLOBを返すINSERTまたはUPDATE文を実行します。

一時LOB

BLOBCLOBおよびNCLOBに対して、一時LOBをインスタンス化できます。一時LOBを表すODP.NET LOBオブジェクトをインスタンス化するには、OracleClobまたはOracleBlobコンストラクタを使用できます。

一時ODP.NET LOBオブジェクトは、次のような場合に使用できます。

グローバリゼーション・サポート

ODP.NETのグローバリゼーション・サポートによって、アプリケーションで、文化によって異なるデータを適切に操作できます。この機能を使用すると、Oracleグローバリゼーション設定に従って適切な文字列フォーマット、日付、時刻、通貨、数値、ソート順序およびカレンダ規則が適用されます。

関連項目:

OracleGlobalizationクラス

この項では、次の項目について説明します。

グローバリゼーション設定

OracleGlobalizationオブジェクトを使用して、次の設定を表すことができます。

クライアント・グローバリゼーション設定

クライアント・グローバリゼーション設定は、ローカル・コンピュータのWindowsレジストリ内のOracleグローバリゼーション設定(NLS_LANG)から導出されます。クライアント・グローバリゼーション・パラメータ設定は読取り専用であり、アプリケーションの存続期間中は変わりません。クライアント・グローバリゼーション設定は、OracleGlobalization.GetClientInfo() staticメソッドをコールすることにより取得できます。

次の例では、クライアント・グローバリゼーション設定を取得しています。

// C#
...
// GetClientInfo() is a static method on OracleGlobalization class
OracleGlobalization ClientGlob = OracleGlobalization.GetClientInfo();

OracleGlobalizationオブジェクトのプロパティにより、Oracleグローバリゼーション値が設定されます。

セッション・グローバリゼーション設定

セッション・グローバリゼーション・パラメータは、最初はクライアント・グローバリゼーション設定と同じです。クライアント設定とは異なり、セッション・グローバリゼーション設定は更新可能です。ただし、セッション・グローバリゼーション設定はデータベース・サーバーへの接続を確立した後でしか取得できません。セッション・グローバリゼーション設定は、OracleConnectionGetSessionInfo()をコールすることにより取得できます。このメソッドをコールすると、セッションのグローバリゼーション設定を表すプロパティを持つOracleGlobalizationオブジェクトのインスタンスが返されます。

OracleConnectionオブジェクトにより、接続が確立されるときに、クライアント・コンピュータのOracleグローバリゼーション(またはNational Language Support(NLS))レジストリ設定で指定されている値で初期化されたグローバリゼーション・パラメータを持つセッションが暗黙的にオープンされます。セッションの設定は更新可能であり、その存続期間中も変更できます。

次の例では、セッションの日付書式設定を変更します。

// C#
...
OracleConnection con = new OracleConnection("User Id=scott;Password=tiger;");
con.Open();
OracleGlobalization SessionGlob = con.GetSessionInfo();

// SetSessionInfo updates the Session with the new value
SessionGlob.DateFormat = "YYYY/MM/DD";
con.SetSessionInfo(SessionGlob);
...

スレッドベースのグローバリゼーション設定

スレッドベースのグローバリゼーション・パラメータ設定は、各スレッドに固有です。これらの設定は、最初はクライアント・グローバリゼーション・パラメータと同じですが、アプリケーションで指定されたとおりに変更できます。ODP.NET型と文字列との間で変換が行われるとき、適用可能であればスレッドベースのグローバリゼーション・パラメータが使用されます。

スレッドベースのグローバリゼーション・パラメータ設定を取得するには、OracleGlobalizationオブジェクトのGetThreadInfo staticメソッドをコールします。スレッドのグローバリゼーション設定を行うには、OracleGlobalizationオブジェクトのSetThreadInfo staticメソッドをコールできます。

文化によって異なるデータを操作する場合、ODP.NETのクラスおよび構造体はOracleGlobalization設定のみに依存します。.NETのスレッド文化情報は使用されません。アプリケーションで.NET型しか使用されない場合、OracleGlobalization設定は影響しません。しかし、ODP.NET型と.NET型の間で変換が行われるときは、適用可能であればOracleGlobalization設定が使用されます。


注意:

System.Threading.Thread.CurrentThread.CurrentCultureが変更されても、スレッドまたはセッションのOracleGlobalizationの設定に影響はありません。またその逆も同様です。


次のコードでは、ODP.NET型によってスレッドのグローバリゼーション設定がどのように使用されるかを示します。

...
OracleGlobalization ThreadGlob = OracleGlobalization.GetThreadInfo();
// set and validate the format
ThreadGlob.DateFormat = "YYYY-MM-DD";

// set the thread with the new format
OracleGlobalization.SetThreadInfo(ThreadGlob);

// create a new instance of OracleDate
OracleDate date = new OracleDate("2002-01-01");
...

OracleGlobalizationオブジェクトでは、そのプロパティに対して行われた変更が検証されます。プロパティの設定に無効な値が使用されている場合、例外がスローされます。TerritoryおよびLanguageプロパティが変更されると、OracleGlobalizationオブジェクトの他のプロパティが暗黙的に変更されますので注意してください。

関連資料:

TerritoryおよびLanguageのグローバリゼーション設定の影響を受けるプロパティの詳細は、『Oracle9i Databaseグローバリゼーション・サポート・ガイド』を参照してください。

グローバリゼーションの影響を受ける操作

この項では、グローバリゼーション設定に依存する、またはこの設定の影響を受けるODP.NET型および操作をリストします。

クライアント・コンピュータのグローバリゼーション設定に依存する操作

OracleString構造体は、クライアント・コンピュータのOracleGlobalization設定によって決まります。GetNonUnicodeメソッドでUnicode文字列をbyte[]に変換する場合、およびbyte[]を受け入れるOracleStringコンストラクタでANSI文字のbyte[]をUnicodeに変換する場合、ローカル・コンピュータのクライアント・キャラクタ・セットが使用されます。

スレッド・グローバリゼーション設定に依存する操作

スレッド・グローバリゼーション設定は、ODP.NET型によって.NET文字列型との間で変換が行われるたびに、適用可能であれば使用されます。ほとんどの場合、ToStringメソッド、Parse staticメソッド、.NET文字列データを受け入れるコンストラクタ、および.NET文字列との間の変換演算子では、使用されるODP.NET型に応じたスレッド・グローバリゼーション設定が使用されます。

たとえば、OracleDate型では、ToStringメソッドがコールされると、スレッド・グローバリゼーション設定のDateFormatプロパティが使用されます。これにより、スレッドの設定で指定されている書式で文字列としてDATEが返されます。

詳細は、第5章でODP.NET型と.NET文字列型の間の変換を行うODP.NET型メソッドに関する備考を読み、その特定のメソッドに対して使用されるスレッド・グローバリゼーション設定を確認してください。

関連項目:

第5章「Oracle.DataAccess.Typesネームスペース(ODP.NET型)」

セッション・グローバリゼーション・パラメータの影響を受ける操作

セッション・グローバリゼーション設定は、文字列としてサーバーから取得される、またはサーバーに送信されるすべてのデータに影響を与えます。

たとえば、TO_CHAR()関数が適用されたDATE列が選択されている場合、DATE列のデータは、セッション・グローバリゼーション設定のDateFormatで指定された日付書式の文字列になります。逆の方向にデータを送信するには、DATE列に挿入する文字列データを、セッション・グローバリゼーション設定のDateFormatプロパティで指定された書式にする必要があります。

また、セッション・グローバリゼーション設定は、安全な型マッピングを使用して文字列としてDataSet内に取得されるデータにも影響を与えます。型の書式が区別される場合、文字列は常に、セッション・グローバリゼーション設定で指定されている書式になります。

たとえば、VARCHAR2およびCHARデータは、適用可能な書式がないため、セッション設定の影響を受けません。しかし、DateFormatおよびNumericCharactersプロパティは、DATE型とNUMBER型が安全な型マッピングを使用してデータベース・サーバーから文字列として取得された場合、それぞれの文字列表現に影響を与える可能性があります。

関連項目:

OracleDataAdapterの安全な型マッピング

DataSetによるデータベース更新時の一意性の確保

この項では、DataTablePrimaryKeyおよびConstraintsプロパティがどのようにOracleDataAdapterによって構成されるかについて説明します。この2つのプロパティは、OracleCommandBuilderDataSetの変更内容がデータベースへ更新される際の一意性を保証します。

データベースに対して実行されるDML文をOracleCommandBuilderオブジェクトを使用して動的に生成するのが、単独のDataTableで行われた変更をデータベースと一致させる方法の1つです。

この場合、1つのDataRowの変更を一致させる際にデータベース内の複数の行に影響(更新または削除)するようなDML文は、OracleCommandBuilderで生成できないようにする必要があります。そうしなければ、OracleCommandBuilderによってデータベース内のデータが破壊される可能性があります。

DataRowの1つの変更が単独の行のみに影響するようにするためには、DataTableのすべての行で一意な値の組合せとなるDataColumnのセットがDataTableに必要です。DataTable.PrimaryKeyおよびDataTable.Constraintsプロパティが指定されたDataColumnのセットがこの条件を満たします。OracleCommandBuilderでは、DataTable.PrimaryKeyがnull以外であるかまたはDataTable.ConstraintsコレクションにUniqueConstraintがあるかどうかがチェックされて、DataTableにおける一意性が判断されます。

ここでは、まずDataRowの一意性を構成する要素について説明し、次にDataTableプロパティの設定を通して更新時にその一意性を維持する方法について説明します。

この項では、次の項目について説明します。

DataRowの一意性を構成する要素

この項では、DataRowの一意性を保証するための最低条件について説明します。次の項で説明する方法でDataTable.PrimaryKeyプロパティおよびDataTable.Constraintsプロパティを設定する前に、一意性の条件を確保しておく必要があります。

次のうち1つでも当てはまればDataTableにおける一意性が保証されます。

PrimaryKeyおよびConstraintsプロパティの設定

「DataRowの一意性を構成する要素」に説明した最低条件を満たしていれば、DataTable.PrimaryKeyまたはDataTable.Constraintsプロパティを設定できます。

これらのプロパティが設定されると、OracleCommandBuilderではDataTable.PrimaryKeyプロパティの設定またはDataTable.ConstraintsコレクションにおけるDataTable.Constraintの有無によってDataTableにおける一意性を判断できます。一意性が確認されれば、OracleCommandBuilderでは更新を実行するDML文を安全に生成できます。

OracleDataAdapter.FillSchemaメソッドは、これらのプロパティの設定を次の優先順位で試みます。

  1. 選択リストに主キーが返された場合、そのキーがDataTable.PrimaryKeyとして設定されます。

  2. 次の条件を満たす列セットが選択リストに返された場合、その列セットがDataTable.PrimaryKeyとして設定されます。

    条件: 列セットに一意制約が定義されているかまたは一意のインデックスが作成されていて、各列にNOT NULL制約が定義されている場合。

  3. 次の条件を満たす列セットが選択リストに返された場合、DataTable.ConstraintsコレクションにUniqueConstraintが追加され、DataTable.PrimaryKeyは設定されません。

    条件: 列セットに一意制約が定義されているかまたは一意のインデックスが作成されていて、少なくとも1つの列にNOT NULL制約が定義されている場合。

  4. 選択リストにROWIDが含まれる場合、それがDataTable.PrimaryKeyとして設定されます。

その他にも、OracleDataAdapter.FillSchemaは次の処理を行います。

PrimaryKeyおよびConstraints設定を使用しない更新

アプリケーションがOracleDataAdapter.FillSchemaをコールしていないといった理由でDataTable.PrimaryKeyまたはConstraintsプロパティが設定されていない場合、OracleCommandBuilderOracleDataAdapter.SelectCommandの選択リストを直接チェックしてDataTableにおける一意性を判断します。ただしこのチェックでは、OracleDataAdapter.SelectCommandSELECT文に対するメタデータを取得するためにサーバー・ラウンドトリップが発生します。

PL/SQL文のメタデータにはキー情報が返されないため、OracleCommandBuilderではPL/SQL文から作成されたDataTableは更新できません。

OracleDataAdapterの安全な型マッピング

次のOracleデータ型は、密接に関連する.NET型に変換される際にデータが失われる可能性があるため、ODP.NETのOracleDataAdapterでは安全な型マッピング機能が提供されます。

これらいずれかの型を含むOracleデータを.NET DataSetに移入すると、データが失われる可能性があります。OracleDataAdapterの安全な型マッピング機能を使用すると、データは失われません。SafeMappingプロパティを適切に設定することにより、これらの型を次のいずれかとしてDataSet内で確実に表すことができます。

考えられるデータ損失

次の各項では、データが失われる可能性のある型および状況について詳しく説明します。

OracleのNUMBER型から.NETのDecimal型へ

Oracleのデータ型NUMBERは最大38精度を保持できますが、.NETのDecimal型は最大28精度しか保持できません。28精度を超えるNUMBERデータ型が.NETのDecimal型内に取得されると、精度が失われます。

表3-12に、OracleのNUMBERおよび.NETのDecimalの最大値と最小値をリストします。

表3-12 OracleのNUMBERと.NETのDecimalの比較
OracleのNUMBER .NETのDecimal

最大値

9.9999999999999999999999999999999999999 e125

79,228,162,514,264,337,593,543,950,335

最小値

-9.9999999999999999999999999999999999999 e125

-79,228,162,514,264,337,593,543,950,335

OracleのDate型から.NETのDateTime型へ

Oracleのデータ型DATEではBCの日付を表すことができますが、.NETのDateTimeでは表すことができません。BCを使用するDATEが.NETのDateTime型内に取得されると、データが失われます。

表3-13に、OracleのDateおよび.NETのDateTimeの最大値と最小値をリストします。

表3-13 OracleのDateと.NETのDateTimeの比較
OracleのDate .NETのDateTime

最大値

Dec 31, 9999 AD

Dec 31, 9999 AD 23:59:59.9999999

最小値

Jan 1, 4712 BC

Jan 1, 0001 AD 00:00:00.0000000

OracleのTimeStamp型から.NETのDateTime型へ

DATEと同様に、Oracleのデータ型TimeStampではBCの日付を表すことができますが、.NETのDateTime型では表すことができません。BCを使用するTimeStampが.NETのDateTime型内に取得されると、データが失われます。OracleのTimeStamp型ではe-9の単位で値を表すことができますが、.NETのDateTime型ではe-7の単位でしか値を表せません。タイム・ゾーンを持つOracleのTimeStampデータ型はタイム・ゾーン情報を格納できますが、.NETのDateTimeは格納できません。

表3-14に、OracleのTimeStampおよび.NETのDateTimeの最大値と最小値をリストします。

表3-14 OracleのTimeStampと.NETのDateTimeの比較
OracleのTimeStamp .NETのDateTime

最大値

Dec 31, 9999 AD 23:59:59.999999999

Dec 31, 9999 AD 23:59:59.9999999

最小値

Jan 1, 4712 BC 00:00:00.000000000

Jan 1, 0001 AD 00:00:00.0000000

OracleのINTERVAL DAY TO SECONDから.NETのTimeSpanへ

DATEと同様に、Oracleのデータ型INTERVAL DAY TO SECONDではBCの日付を表すことができますが、.NETのTimeSpan型では表すことができません。BCを使用するINTERVAL DAY TO SECONDが.NETのTimeSpan型内に取得されると、データが失われます。OracleのINTERVAL DAY TO SECOND型ではe-9の単位で値を表すことができますが、.NETのTimeSpan型ではe-7の単位でしか値を表せません。

表3-15に、OracleのINTERVAL DAY TO SECOND および.NETのTimeSpanの最大値と最小値をリストします。

表3-15 OracleのINTERVAL DAY TO SECONDと.NETのTimeSpanの比較
OracleのINTERVAL DAY TO SECOND .NETのTimeSpan

最大値

+999999999 23:59:59.999999999

+10675199 02:48:05.4775807

最小値

-999999999 23:59:59.999999999

-10675199 02:48:05.4775808

SafeMappingプロパティ

デフォルトでは、安全な型マッピングは使用不可になっています。

安全な型マッピングの使用

安全な型マッピング機能を使用するには、OracleDataAdapter.SafeMappingプロパティを、キーと値のペアのハッシュテーブルで設定する必要があります。このキーと値のペアで、データベース表の列名(型string)を.NET型(型Type)にマップする必要があります。ODP.NETでは、byte[]およびString型への安全な型マッピングがサポートされています。これ以外の型マッピングを行うと、例外が発生します。

設計時に列名が不明な場合は、必要に応じてアスタリスク(*)を使用し、データベース型のすべてのデータを安全な.NET型にマップできます。有効な列名とアスタリスクの両方がある場合、列名が使用されます。


注意:

  • データベース表の列名の大文字と小文字は区別されます。

  • 無効な列名に対応するハッシュテーブル内の列名は、無視されます。


.NET文字列へのマッピング

文字列としての安全な型マッピングは、読み込みやすく、追加の変換が必要ありません。特定のOracleデータ型を文字列に変換するには、追加の変換を行う必要があります。この変換は、byte[]への変換よりも時間がかかる可能性があります。.NETの文字列をODP.NET型に戻す変換は、セッションの書式設定情報に基づいて行われます。

OracleDataAdapterのRequeryプロパティ

OracleDataAdapterRequeryプロパティにより、OracleDataAdapterFillコールに対して、最初のFillコールの後で問合せを再実行するかどうかを制御します。

OracleDataAdapterFillメソッドを使用すると、DataSet内のデータを追加またはリフレッシュできます。それ以降のFillコールで同じ問合せを使用してDataSetを追加する場合は、問合せを再実行しないほうがよい場合があります。

Requeryプロパティがtrueに設定されている場合、それ以降のFillコールによって問合せが再実行され、DataSetにデータが埋め込まれます。これは負荷がかかる操作なので、再実行が必要でなければ、Requeryfalseに設定してください。SelectCommandプロパティまたは関連するパラメータのいずれかを変更する必要がある場合は、Requerytrueに設定してください。

Requeryプロパティがfalseに設定されている場合、DataSetにはある時点のスナップショットとしてのデータ全体が含まれます。問合せは最初のFillコールに対してのみ実行され、それ以降のFillコールでは、問合せの最初の実行でオープンされたカーソルからデータがフェッチされます。この機能がサポートされるのは、順方向専用のフェッチについてのみです。Fillコールで、最後にフェッチされた行より前の行をフェッチしようとすると、例外が呼び出されます。最初のFillコールに使用された接続は、それ以降のFillコールに対しても使用可能である必要があります。

DataSetOracleRefCursorを埋め込む際も、同様の方法でRequeryプロパティを使用できます。Requeryプロパティをfalseに設定すると、最初のFillに使用された接続とOracleRefCursorの両方が、それ以降のFillコールに対して使用可能である必要があります。

関連項目:

デバッグ・トレース

ODP.NETでは、すべてのODP.NETアクティビティをトレース・ファイルにロギングできるデバッグ・トレースがサポートされています。様々なレベルのトレースが可能です。

プロバイダでは、次の情報を記録できます。

トレース・コールのためのレジストリ設定

後述のレジストリ設定は、次のディレクトリの下に構成してください。

HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET

TraceFileName

TraceFileNameの有効な値は、任意の有効なパスおよびファイル名です。

TraceFileNameでは、トレース情報のロギングに使用されるファイル名を指定します。TraceOption0に設定されている場合、名前がそのまま使用されます。しかし、TraceOption1の場合、指定されたファイル名にスレッドIDが追加されます。

関連項目:

TraceOption

TraceLevel

TraceLevelの有効な値は、次のとおりです。

TraceLevelでは、ODP.NETでのトレース・レベルを指定します。すべてのオブジェクトに対する入力コールと出力コールすべてをトレースすると負荷がかかるため、TraceLevelを指定して、トレースをプロバイダの特定の領域に制限します。

複数のオブジェクトについてのトレースを取得するには、有効な値を追加するだけです。たとえば、TraceLevel3に設定されている場合、トレース情報は入力、出力、SQLおよび接続プーリング情報についてロギングされます。

TraceOption

TraceOptionの有効な値は、次のとおりです。

TraceOptionでは、各スレッドIDについてトレース情報を1つのファイルにロギングするか複数のファイルにロギングするかを指定します。1つのトレース・ファイルを指定した場合、TraceFileName内に指定されているファイル名が使用されます。複数のトレース・ファイル・オプションを要求した場合、スレッドごとにトレース・ファイルを作成するために、指定されているファイル名にスレッドIDが追加されます。

ODP.NETでのXMLサポート

Oracle8iリリース8.1.7以降、Oracleではリレーショナルまたはオブジェクト・リレーショナルの表およびビューからデータをXML文書として抽出できます。データベース・サーバーに対する挿入、更新および削除操作にXML文書を使用することも可能です。

Oracle9iリリース2(9.2)では、高パフォーマンスなXMLの格納と取得に関連した特定のテクノロジ群であるOracle XMLデータベースによって、XMLがデータベース内でネイティブにサポートされます。Oracle XMLデータベースは、SQLとXML双方のデータ・モデルを取り入れて高次元の相互操作を可能にしたOracleの発展形で、ネイティブなXMLサポートを提供します。


注意:

Oracle8iリリース8.1.7およびOracle9iリリース1(9.0.1)では、OracleCommandの特定のメソッドはOracle9i以上のXML Developer's Kit(Oracle XDK)がデータベースにインストールされていることを必要とします。XDKは、Oracle Technology Network Japan(OTN-J)からダウンロードできます。


ODP.NETのXMLサポートに関連したサンプルは、次のディレクトリに用意されています。

%ORACLE_HOME%\ODP.NET\Samples

この項では、次の項目について説明します。

サポートされるXML機能

ODP.NETでは次のXML機能がサポートされます。

.NETアプリケーションの開発者が利用できる具体的な機能は次のとおりです。

OracleXmlTypeと接続の依存性

OracleXmlTypeオブジェクトの読取り専用のConnectionプロパティには、OracleXmlTypeオブジェクトのインスタンス化に使用されたOracleConnectionオブジェクトへの参照が格納されます。

OracleXmlTypeオブジェクトがOracleConnectionオブジェクトへの参照を取得する方法は、OracleXmlTypeオブジェクトがどのようにインスタンス化されたかによって決まります。

ある接続に関連付けられたOracleXmlTypeオブジェクトは、別の接続では使用できません。たとえば、あるOracleXmlTypeオブジェクトをOracleConnection Aを使用して取得した場合、そのオブジェクトはOracleConnection Bを使用するコマンドの入力パラメータには使用できません。OracleXmlTypeオブジェクトのConnectionプロパティをチェックすれば、OracleXmlTypeオブジェクトがその接続プロパティで参照しているOracleConnectionのコンテキスト内でのみ使用されていることをアプリケーションで確認できます。そうでない場合、ODP.NETでは例外が呼び出されます。

データベース・サーバーでのXMLTypeデータの更新

XMLType列の更新にはトランザクションは必要ありません。ただし、データベースの更新処理全体をトランザクションにカプセル化することを強くお薦めします。そうすれば、エラーが発生したときでも更新をロールバックできます。

データベース内のXMLType列は、Oracle Data Provider for .NETを使用していくつかの方法で更新できます。

DataSet、OracleDataAdapterおよびOracleCommandBuilderでの更新

XMLType列がDataSetにフェッチされている場合、XMLTypeデータは.NET Stringとして表されます。

DataSet内のXMLTypeデータの更新には特別な操作は必要ありません。XMLTypeデータは、DataSetに格納されている他のデータと同じ方法で変更できます。変更が行われてOracleDataAdapter.Update()が起動されると、OracleDataAdapterXMLTypeデータを適切に処理します。OracleDataAdapterは、提供されたあらゆるカスタムのSQL INSERTUPDATEまたはDELETE文を使用します。または、データベース・サーバーに変更をフラッシュするために必要な有効なSQL文がOracleCommandBuilderによって生成されます。

OracleCommandおよびOracleParameterでの更新

OracleCommandは、特にOracleParameterを使用した場合にXMLTypeデータの更新に威力を発揮します。データベース表の列を更新するには、新しい値をコマンドの入力パラメータとして渡すことができます。

入力バインド

データベース内のXMLType列を更新するには、静的な値を使用してSQL文を実行できます。さらに、SQL文、無名PL/SQLブロックまたはストアド・プロシージャに入力パラメータをバインドしてXMLType列を更新できます。パラメータ値は.NET Framework型、ODP.NET型またはOracleXmlTypeオブジェクトとして設定できます。

XMLType列はOracleXmlTypeオブジェクトを使用して更新できますが、OracleXmlTypeオブジェクトのインスタンスがあるからといってデータベース内のXMLType列を更新できるとは限りません。

OracleXmlType列へのnull値の設定

アプリケーションでデータベース内のXmlType列をnull値に設定できます。入力バインドを使用する方法と使用しない方法があります。

XMLType列への空のXMLデータの設定

OracleXmlTypeでのXMLデータの更新

OracleXmlTypeオブジェクトでXMLデータを更新する方法はいくつかあります。

XMLの特殊文字

次の文字はXMLでは特別な意味を持ちます。詳細は、XML 1.0の仕様書を参照してください。

表3-16 特殊文字
特殊文字 XMLでの意味 エンティティ・コード

<

XMLタグの開始

&lt;

>

XMLタグの終了

&gt;

"

引用符

&quot;

'

アポストロフィまたは一重引用符

&apos;

&

アンパサンド

&amp;

これらの文字がXML要素にデータとして出現した場合、該当するエンティティ・コードに置き換えられます。

また、特定の文字はXML要素名には使用できません。SQL識別子(列名など)がXML要素名にマッピングされる際、該当する文字はUnicodeのエンコードに基づく16進数の先頭にアンダースコアと小文字のX、末尾にアンダースコアを加えた文字列に変換されます。たとえば、スペースはXML要素名には使用できません。SQL識別子にスペースが含まれていた場合、対応するXML要素名では、スペースのUnicodeエンコードに基づいて該当箇所が_x0020_に置き換えられます。

問合せ結果セットのXMLとしての取得

この項では、SQL問合せの結果セットをXMLデータとして取得する方法について説明します。

日付/時刻書式の処理

表3-17に、日付および時刻書式の処理をデータベースのリリース別に記載します。

表3-17 リリース別データ取得時の日付/時刻
データベース・リリース サポートされる日付/時刻書式

Oracle8iリリース8.1.7およびOracle9iリリース1(9.0.x

OracleのDATETIMESTAMPTIMESTAMP WITH TIME ZONE型のデータは、結果のXML文書内では必ずISOの日付/時刻書式であるYYYY-MM-DDThh:mm:ss.sss(ISO書式)として取得されます。

ISOの日付/時刻書式をOracleの日付/時刻書式で表すとYYYY-MM-DD "T"HH:MI:SS.FF3となります。

Oracle9i リリース2(9.2.x

OracleのDATE型データは、セッション中にNLS_DATE_FORMATを使用して指定された書式で取得されます。

TIMESTAMPおよびTIMESTAMP WITH TIME ZONE型データは、セッション中にNLS_TIMESTAMP_FORMATおよびNLS_TIMESTAMP_TZ_FORMATを使用して指定された書式で取得されます。

結果のXML文書をリリース8.1.7、1(9.0.x)または2(9.2.x)のデータベースへ変更を保存するために使用する場合、DATEおよびTIMESTAMPデータはすべてISOの日付/時刻書式であるYYYY-MM-DDThh:mm:ss.sss(ISO書式)でXML文書内に取得する必要があります。

そのためには、問合せが実行される前に次のNLSセッション・パラメータに対してALTER SESSIONコマンドをセッションで明示的に実行する必要があります。

  • NLS_DATE_FORMAT: Oracleの日付/時刻書式YYYY-MM-DD"T"HH:MI:SSに設定します。

  • NLS_TIMESTAMP_FORMAT: Oracleの日付/時刻書式YYYY-MM-DD"T"HH:MI:SS.FF3に設定します。

  • NLS_TIMESTAMP_TZ_FORMAT: Oracleの日付/時刻書式YYYY-MM-DD"T"HH:MI:SS.FF3に設定します。

列データの特殊文字

問合せ内の選択リスト列にXMLで特別な意味を持つ文字(表3-16を参照)を含むデータがあった場合、その文字は結果のXML文書では対応するエンティティ・コードに置き換えられます。

次の例は、列データ内のかぎカッコの特殊文字がODP.NETでどのように処理されるかを示しています。

// Create the following table
create table specialchars ("id" number, name varchar2(255));
insert into specialchars values (1, '<Jones>');

// Create the connection
string constr = "User Id=hr;Password=hr;Data Source=orcl";
OracleConnection conn = new OracleConnection(constr);
conn.Open();

// Create the command
OracleCommand cmd = new OracleCommand("", conn);

// Set the XML command type to query.
cmd.XmlCommandType = OracleXmlCommandType.Query;

// Set the SQL query
cmd.CommandText = "select * from specialchars";

// Set command properties that affect XML query behavior.
cmd.BindByName = true;

// Set the XML query properties
cmd.XmlQueryProperties.MaxRows = -1;

// Get the XML document as an XmlReader.
XmlReader xmlReader = cmd.ExecuteXmlReader();
XmlDocument xmlDocument = new XmlDocument();
xmlDocument.PreserveWhitespace = true;
xmlDocument.Load(xmlReader);
Console.WriteLine(xmlDocument.OuterXml);

この表に対して次のXML文書が生成されます。

<?xml version = '1.0'?>
<ROWSET>
   <ROW>
      <id>1</id >
      <NAME>&lt;Jones&gt;</NAME>
   </ROW>
</ROWSET>

表名またはビュー名の特殊文字

表またはビューの名前にアンダースコア(_)以外の非英数字が含まれる場合、表名またはビュー名を引用符で囲みます。

たとえば、test'ingという名前の表からすべてのエントリを選択するには、OracleCommandオブジェクトのCommandTextプロパティを次の文字列に設定します。

"select * from \"test'ing\"";

列名をXML要素名へマッピングする際の大文字/小文字の区別

SQL識別子(列名)からXML要素名へのマッピングでは大文字/小文字が区別され、要素名における大文字/小文字は表またはビューの列名とまったく同じとなります。

ただし、ルート・タグおよび行タグでは大文字/小文字は区別されません。次の例では、この状況での大文字/小文字の区別方法を示します。

//Create the following table
create table casesensitive_table ("Id" number, NAME varchar2(255));

//insert name and id
insert into casesensitive_table values(1, `Smith');

The following XML document is generated:
<?xml version = '1.0'?>
  <ROWSET>
    <ROW>
      <Id>1</Id>
      <NAME>Smith</NAME>
    </ROW>
  </ROWSET>

Id列に対する要素名では、列名と同じように大文字/小文字が区別されています。

列名からXML要素名へのマッピング

SQL問合せで生成される各行では、SQL識別子(列名)はXML文書内のXML要素にマッピングされます。

次の例はこの状況を示しています。

// Create the following table
create table emp_table (EMPLOYEE_ID NUMBER(4), LAST_NAME varchar2(25));
// Insert some data
insert into emp_table values(205, `Higgins');

select * from emp_tableというSQL問合せによって次のXML文書が生成されます。

<?XML version="1.0"?>
  <ROWSET>
    <ROW>
      <EMPLOYEE_ID>205</EMPLOYEE_ID>
      <LAST_NAME>Higgins</LAST_NAME>
    </ROW>
  </ROWSET>

employees表のEMPLOYEE_IDおよびLAST_NAMEという2つのデータベース列は、生成されたXML文書のEMPLOYEE_IDおよびLAST_NAMEという2つの要素にマッピングされます。

Oracle8iリリース8.1.7からの結果取得

Oracle8iリリース8.1.7のデータベースから問合せ結果をXMLとして取得する場合、問合せ選択リスト内のSQL識別子には、XML要素名に無効な文字を使用できません。Oracle8iリリース8.1.7ではこの問題に対処するサポートがないため、次の例のようなSQL問合せを使用してspecialchars表から結果をXML文書として取得します。

select "some id" as "some_x0020_id", name from specialchars;
Oracle9i以上からの結果取得

Oracle9i以上のデータベースから問合せ結果をXMLとして取得する場合、問合せ選択リスト内のSQL識別子には、XML要素名に無効な文字を使用できます。このようなSQL識別子(列名など)がXML要素名にマッピングされる際、該当する各文字はUnicodeのエンコードに基づく16進数の先頭にアンダースコアと小文字のX、末尾にアンダースコアを加えた文字列に変換されます。

したがってOracle9iデータベースでは、次のSQL問合せを使用してspecialchars表から結果をXML文書として取得できます。

select "some id", name from specialchars;

関連項目:

無効なXML要素名の処理の詳細は、「XMLの特殊文字」を参照してください。

デフォルト・マッピングの改良

SQL識別子からXML要素名へのデフォルトのマッピングが適切でなければ、次の方法でマッピングを改良できます。

オブジェクト・リレーショナル・データ

ODP.NETでは、オブジェクト・リレーショナルな列、表およびビューに格納されたデータに対してXML文書を生成できます。

次の例はこの状況を示しています。


// Create the following tables and types
CREATE TYPE "EmployeeType" AS OBJECT (EMPNO NUMBER, ENAME VARCHAR2(20));
/
CREATE TYPE EmployeeListType AS TABLE OF "EmployeeType";
/
CREATE TABLE mydept (DEPTNO NUMBER, DEPTNAME VARCHAR2(20),
              EMPLIST EmployeeListType)
              NESTED TABLE EMPLIST STORE AS EMPLIST_TABLE;
INSERT INTO mydept VALUES (1, 'depta',
              EmployeeListType("EmployeeType"(1, 'empa')));

この表に対して次のXML文書が生成されます。

<?xml version = "1.0"?>
<ROWSET>
   <ROW>
      <DEPTNO>1</DEPTNO>
      <DEPTNAME>depta</DEPTNAME>
      <EMPLIST>
         <EmployeeType>
            <EMPNO>1</EMPNO>
            <ENAME>empa</ENAME>
         </EmployeeType>
      </EMPLIST>
   </ROW>
</ROWSET>

ODP.NETは、コレクション要素内の各項目を、コレクション内での要素のデータベース型名で囲みます。mydept表はEMPLISTデータベース列内にコレクションがあり、コレクション内の各項目の型はEmployeeTypeです。したがって、XML文書ではコレクション内の各項目が型名のEmployeeTypeで囲まれます。

null値

データベース行にnull値の列があった場合、生成されるXML文書ではその行に対してnull値の列は含まれません。

XMLを使用したデータ操作

この項では、XMLを使用してデータベースに変更を加える方法について説明します。

日付/時刻書式の処理

表3-18に、日付および時刻書式の処理をデータベースのリリース別に記載します。

表3-18 リリース別データ保存時の日付および時刻
データベース・リリース サポートされる日付/時刻書式

Oracle8iリリース8.1.7、Oracle9iリリース1(9.0.x)およびOracle9iリリース2(9.2.x

DATETIMESTAMPおよびTIMESTAMP WITH TIME ZONE型のデータはすべて、XML文書内ではISOの日付/時刻書式であるYYYY-MM-DDThh:mm:ss.sss(ISO書式)で指定する必要があります。

XMLを使用した変更内容の保存

XMLデータを使用してデータベースの表およびビューへ変更を保存できます。ただし、1つのXML文書で挿入、更新および削除操作を組み合せることはできません。ODP.NETでは、単独のXML文書を受け入れ、どの変更が挿入、更新または削除操作であるかを判断することはできません。

挿入は挿入される行だけ、更新は更新される行だけ、削除は削除される行だけを含むXML文書で行います。

たとえば、HRサンプル・スキーマに含まれるemployees表を使用した場合、次の問合せを指定できます。

select employee_id, last_name from employees where employee_id = 205;

次のXML文書が生成されます。

<?xml version = '1.0'?>
<ROWSET>
   <ROW>
      <EMPLOYEE_ID>205</EMPLOYEE_ID>
      <LAST_NAME>Higgins</LAST_NAME>
   </ROW>
</ROWSET>

従業員205の名前をHigginsからSmithへ変更するには、employees表および変更内容を含むXMLデータを次のように指定します。

<?xml version = '1.0'?>
<ROWSET>
   <ROW>
      <EMPLOYEE_ID>205</EMPLOYEE_ID>
      <LAST_NAME>Smith</LAST_NAME>
   </ROW>
</ROWSET>

列データの特殊文字

XML文書の要素内のデータにXMLで特別な意味を持つ文字(表3-16を参照)が含まれる場合、データベース表の列にデータが正しく格納されるよう、XML文書ではこれらの文字をエンティティ・コードに置き換えるかエスケープする必要があります。そうでない場合、ODP.NETでは例外がスローされます。

次の例は、列データ内のかぎカッコの特殊文字がODP.NETでどのように処理されるかを示しています。

// Create the following table
create table specialchars ("id" number, name varchar2(255));

specialchars表に値(1, `<Jones>')を挿入するには、次のXML文書を使用できます。

<?xml version = '1.0'?>
 <ROWSET>
  <ROW>
   <id>1</id >
   <NAME>&lt;Jones&gt;</NAME>
  </ROW>
 </ROWSET>

表名またはビュー名の特殊文字

表またはビューの名前にアンダースコア(_)以外の非英数字が含まれる場合、表名またはビュー名を引用符で囲みます。

たとえば、test'ingという名前の表に変更を保存するには、OracleCommand.XmlSaveProperties.TableNameプロパティを"\"test'ing\""に設定します。

XML要素名を列名へマッピングする際の大文字/小文字の区別

XML文書でデータの行を表す各XML要素の子要素が、データベースの列名に対応します。子要素の名前から列名へのマッピングでは常に大文字/小文字が区別されますが、ルート・タグおよび行タグ名では区別されません。次の例はこの状況を示しています。

//Create the following table
create table casesensitive_table ("Id" number, NAME varchar2(255));

casesensitive_table表に値(1, Smith)を挿入するには、次のXML文書を使用できます。

<?xml version = '1.0'?>
  <ROWSET>
    <ROW>
      <Id>1</Id>
      <NAME>Smith</NAME>
    </ROW>
  </ROWSET>

Id列に対する要素名では、列名と同じように大文字/小文字が区別されています。

XML要素名から列名へのマッピング

Oracle9i以上では、XMLをデータベースでのデータ操作に使用する場合、XML要素名から列名へのマッピング方法がOracle8iリリース8.1.7とは異なります。この項では、次のspecialchars表のsome id列を例にあげながら、この違いについて説明します。

// Create the specialchars table
create table specialchars ("some id" number, name varchar2(255));

specialchars表には、スペースを含むsome id列があります。スペースはXML要素名には使用できません。

Oracle 8.1.7への変更の保存

この場合、Oracle 8.1.7データベースでXML文書を使用してspecialchars表に変更を保存するには、表に対してビューを作成した上で、XMLデータを使用して変更をビューへ保存する必要があります。

表のsome id列に対応するビューでの列名には、次の例のように無効な文字を除いた列名か、またはエスケープした列名のどちらかを使用できます。

// Create the view with the escaped column name
create view view1(some_x0020_id, name) as select * from specialchars;

// Create the view with the column name with no invalid character
create view view2(someid, name) as select * from specialchars;

specialchars表にview1を使用して値(1, <Jones>)を挿入するには、次のXML文書を使用できます。

<?xml version = '1.0'?>
  <ROWSET>
    <ROW>
      <SOME_X0020_id>1</SOME_X0020_id >
      <NAME>&lt;Jones&gt;</NAME>
    </ROW>
  </ROWSET>

specialchars表にview2を使用して値(1, <Jones>)を挿入するには、次のXML文書を使用できます。

<?xml version = '1.0'?>
  <ROWSET>
    <ROW>
      <SOMEID>2</SOMEID>
      <NAME>&lt;Jones&gt;</NAME>
      </ROW>
  </ROWSET>

Oracle9i以上への変更の保存

XML文書を使用して表またはビューへ変更を保存する場合、OracleCommand.XmlSaveProperties. UpdateColumnsListを使用して更新または挿入する列のリストを指定します。

Oracle9i以上では、XML文書を使用して表またはビューの列へ変更を保存するときに、該当する列名にXML要素名に使用できない文字が含まれる場合、次の例のようにUpdateColumnsListプロパティにエスケープした列名を指定する必要があります。

specialchars表に値(2, <Jones>)を挿入するには、次のXML文書を使用できます。

<?xml version = '1.0'?>
  <ROWSET>
    <ROW>
      <some_x0020_id>2</some_x0020_id>
      <NAME>&lt;Jones&gt;</NAME>
    </ROW>
  </ROWSET>

次のコード例は、更新または挿入する列のリストを指定しています。

CmdObj.XmlCommandType = OracleXmlCommandType.Insert;
CmdObj.XmlSaveProperties.Table = "specialchars";
string[] ucols = new string[2];
ucols[0] = "some_x0020_id";
ucols[1] = "NAME";
CmdObj.XmlSaveProperties.UpdateColumnsList = ucols;
CmdObj.ExecuteNonQuery();
デフォルト・マッピングの改良

デフォルトのマッピングが適切でない場合には、次の方法でマッピングを改良できます。

オブジェクト・リレーショナル・データ

XML文書内の変更はオブジェクト・リレーショナル・データへも保存できます。コレクション内の各項目は、次のいずれかの方法でXML文書に指定できます。

複数の表

Oracleでは、結合された複数のリレーショナル表へ変更を保存することはできません。この場合、該当するリレーショナル表に対してビューを作成し、そのビューを更新することをお薦めします。ビューが更新できない場合には、かわりにトリガーを使用できます。

関連資料:

CREATE VIEWコマンドの説明および構文は、『Oracle9i SQLリファレンス』を参照してください。

コミット

XML文書が変更されると、すべての変更がコミットされるか、またはエラーが発生した場合にはすべての変更がロールバックされます。


Go to previous page Go to next page
Oracle
Copyright © 2002, 2003 Oracle Corporation.

All Rights Reserved.
Go To Table Of Contents
目次
Go To Index
索引