| Oracle® Data Provider for .NET開発者ガイド リリース9.2.0.4 部品番号 B13807-01 |
|
この章では、Oracle Data Provider for .NETのプロバイダ固有の機能と、これらの機能を使用して.NETアプリケーションを開発する方法について説明します。
この章の項目は次のとおりです。
この項では、次のようなOracleConnectionプロバイダ固有の機能について説明します。
表 3-1に、サポートされる接続文字列属性をリストします。
次の例では、接続文字列属性を使用してOracleデータベース・サーバーに接続しています。
// C# ... OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;"; con.Open(); ...
| 関連項目:
接続属性の詳細は、「ConnectionString」を参照してください。 |
ODP.NET接続プーリングを有効および無効にするには、Pooling接続文字列属性を使用します。デフォルトでは、接続プーリングは有効です。接続プーリング・サービスの動作を制御するConnectionString属性は、次のとおりです。
Pooling
Connection Lifetime
Connection Timeout
Max Pool Size
Min Pool Size
Incr Pool Size
Decr Pool Size
次のコードでは、接続プーリングに関連付けられた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の属性値と完全に一致するプールがない場合、新しい接続プールが接続プーリング・サービスによって作成されます。要求されたシグネチャのプールが存在する場合、そのプールからアプリケーションへ接続が返されます。
接続プールが作成される際、接続プーリング・サービスでは、まずConnectionStringのMin Pool Size属性で定義されている数の接続が作成されます。接続プールに対して、接続プーリング・サービスによってこの接続数が常に保たれます。
これらの接続は、プール内で使用可能な状態となっているか、アプリケーションで使用されているかのどちらかです。
ConnectionStringのIncr Pool Size属性によって、接続プール内で追加の接続が必要な場合に接続プーリング・サービスにより作成される新規の接続の数が定義されます。
アプリケーションにより接続がクローズされると、接続プーリング・サービスにより、接続の存続期間がConnection Lifetime属性を超えていないかどうかが判断されます。この値を超えている場合、接続プーリング・サービスにより接続がクローズされます。超えていない場合、接続は接続プールに戻ります。接続プーリング・サービスによりConnection Lifetimeが強制されるのは、接続が接続プールに戻ろうとするときのみです。
ConnectionStringのMax Pool Size属性によって、接続プールの最大接続数が設定されます。新しい接続が要求されたが使用可能な接続がなく、Max Pool Sizeの値に達している場合、接続プーリング・サービスは、Connection Timeoutで定義されている時間待機します。Connection Timeoutを経過した後もプール内に使用可能な接続がない場合、接続プーリング・サービスによって、接続要求が時間切れとなったことを示す例外が呼び出されます。
接続プーリング・サービスにより、接続は、使用されていない場合クローズされます。接続は3分ごとにクローズされます。ConnectionStringのDecr Pool Size属性によって、1回の実行でクローズできる最大接続数が接続プーリング・サービスに指定されます。
Oracleデータベース・サーバーでは、データベース・ユーザーの認証にWindowsユーザー・ログイン資格証明を使用できます。Windowsユーザー・ログイン資格証明を使用して接続をオープンするには、ConnectionString属性のUser Idを/に設定する必要があります。Passwordが指定されている場合、この値は無視されます。
// C# ... OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=/;Data Source=oracle;"; con.Open(); ...
Oracleでは、データベース管理者はSYSDBA権限またはSYSOPER権限のいずれかを使用してOracleデータベース・サーバーに接続できます。これは、ConnectionStringのDBA 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で接続するために、OracleConnectionのOpenWithNewPasswordメソッドを使用しています。
// 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」を参照してください。 |
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(); ...
透過的アプリケーション・フェイルオーバー(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型は、構造体またはクラスとして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データ型をリストします。
OracleCommandオブジェクトのExecuteReaderメソッドにより、読取り専用で、順方向のみの結果セットであるOracleDataReaderオブジェクトが返されます。
この項では、OracleDataReaderに関する次の情報を示します。
OracleDataReaderでは、次の2種類の型指定のアクセッサが提供されます。
表3-3に、ODP.NETでサポートされているすべてのOracle固有のデータベース型と、そのOracle固有の型を最も適切に表す対応する.NET型をリストします。3列目は、.NET型として取得するOracle固有の型に対して起動できる有効な型指定のアクセッサを示しています。列に対して無効な型指定のアクセッサが使用されると、InvalidCastExceptionがスローされます。Oracle固有のデータ型は、データベースのバージョンによって異なります。このため、一部のデータ型は旧バージョンのOracleでは使用できません。
ODP.NETは、Oracle固有のデータ型を表すプロバイダ固有の型を公開します。これらのODP.NET型は、対応する.NET型では実現できないパフォーマンスと機能を提供することがあります。ODP.NET型は、それぞれの型指定のアクセッサを呼び出してOracleDataReaderから取得します。
| 関連項目:
すべてのODP.NET型のリストは、「ODP.NET型の概要」を参照してください。 |
表3-4に、ODP.NETでOracle固有の型に対応するODP.NET型を取得する際に使用される、有効な型アクセッサをリストします。
LONGまたはLONG RAWの列型を含むOracleDataReaderが作成されると、OracleDataReaderを作成したOracleCommandのInitialLONGFetchSizeプロパティの値がOracleDataReaderによってチェックされ、その列データをすぐにフェッチする必要があるかどうかが判断されます。
デフォルトでは、InitialLONGFetchSizeは0に設定されています。OracleCommandのInitialLONGFetchSizeプロパティの値が0のままであれば、LONGまたはLONG RAWデータ全体の取得が、アプリケーションによってデータが明示的に要求されるまで延期されます。InitialLONGFetchSizeプロパティがゼロ以外の値に設定されている場合、その値の文字数またはバイト数までLONGまたはLONG RAWデータが即座にフェッチされます。
ODP.NETでは、CommandBehavior.SequentialAccessはサポートされません。このため、LONGおよびLONG RAWデータは、ランダムにフェッチできます。
InitialLONGFetchSizeのバイト数または文字数を超えるデータを取得するためには、選択リストに次のいずれかが含まれている必要があります。
要求されたデータは、適切な型指定のアクセッサ・メソッド(LONGの場合はGetOracleStringまたはGetString、LONG RAWの場合はGetOracleBinaryまたはGetBytes)がOracleDataReaderオブジェクトでコールされると、データベースからフェッチされます。
非遅延モードでデータをフェッチする場合、または選択リストの列に主キー列、ROWIDまたは一意な列群のいずれもない場合は、OracleCommandオブジェクトのInitialLONGFetchSizeプロパティのサイズを、取得するバイトまたは文字数以上に設定してください。
LOBの列型を含むOracleDataReaderが作成されると、OracleDataReaderを作成したOracleCommandのInitialLOBFetchSizeプロパティの値がOracleDataReaderによってチェックされ、LOBの列データをすぐにフェッチする必要があるかどうかが判断されます。デフォルトでは、InitialLOBFetchSizeは0に設定されています。OracleCommandのInitialLOBFetchSizeプロパティの値が0のままであれば、LOBデータ全体の取得が、アプリケーションによってデータが明示的に要求されるまで延期されます。InitialLOBFetchSizeプロパティがゼロ以外の値に設定されている場合、その値の文字数またはバイト数までLOBデータが即座にフェッチされます。
デフォルトのままInitialLOBFetchSizeプロパティが0の場合、OracleDataReaderにGetOracleBlob()およびGetOracleClob()を起動してOracleBlobおよびOracleClobオブジェクトを取得できます。ただしInitialLOBFetchSizeがゼロ以外の値に設定されている場合、GetOracleBlob()およびGetOracleClob()メソッドは無効です。その場合には、GetBytes()およびGetChars()をそれぞれ使用してBLOBおよびCLOBデータをフェッチする必要があります。
InitialLOBFetchSizeをデフォルト以外の値に設定すると、特定のケースでパフォーマンスを向上させることができます。InitialLOBFetchSizeをGetBytes()および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オブジェクトでコールされると、データベースからフェッチされます。InitialLOBFetchSizが0に設定されている場合には、主キー列は必要ありません。
非遅延モードでデータをフェッチする場合、または選択リストの列に主キー列、ROWIDまたは一意な列群のいずれもない場合は、OracleCommandオブジェクトのInitialLOBFetchSizeプロパティのサイズを、取得するバイト数または文字数以上に設定してください。
アプリケーションのパフォーマンスは、アプリケーションがフェッチしなければならない行数と、それらの取得に必要なデータベース・ラウンドトリップの数によって決まります。
FetchSizeプロパティは、1回のサーバー・ラウンドトリップでフェッチされたデータをキャッシュするためにODP.NETで割り当てられるメモリーの合計サイズをバイトで表します。
FetchSizeプロパティは、状況に応じてOracleCommandまたはOracleDataReaderのどちらにも設定できます。また、OracleCommandのFetchSizeプロパティはOracleDataReaderに継承されますが、これは変更可能です。
FetchSizeプロパティがOracleCommandに設定されている場合、新しく作成されるOracleDataReaderにはOracleCommandのFetchSizeプロパティが継承されます。継承されたFetchSizeはそのままにすることも、変更してオーバーライドすることもできます。OracleDataReaderオブジェクトのFetchSizeプロパティは、FetchSizeで指定されたメモリーを割り当てる最初のReadメソッドの起動前に変更します。その後のデータベースからのフェッチでは、すべてそのOracleDataReaderに割り当てられたキャッシュが使用されます。したがって、最初のReadメソッドが起動された後でFetchSizeを変更しても効果はありません。
FetchSizeプロパティを調整すれば、メモリーの使用と1回のサーバー・ラウンドトリップでフェッチされる行数をアプリケーションで制御し、パフォーマンスを改善することができます。たとえばある問合せで100行が返され、各行が1024バイトを使用する場合、FetchSizeを102400に設定すると、その100行をフェッチするのに必要なサーバー・ラウンドトリップは1回のみになります。同じ問合せで、FetchSizeを10240に設定した場合、100行を取得するのに必要なサーバー・ラウンドトリップは10回になります。結果セットからすべての行をフェッチする必要のあるアプリケーションの場合、最初の設定の方が処理速度は速くなります。ただし、結果セットの最初の10行だけを必要とするアプリケーションでは、100行ではなく10行だけをフェッチする2つ目の設定の方が高いパフォーマンスを得ることができます。
OracleCommandオブジェクトのRowSizeプロパティには、SELECT文の実行後に行サイズ(バイト)が移入されます。FetchSizeプロパティは、このRowSizeプロパティに各サーバー・ラウンドトリップでフェッチする行数を掛けた値に設定できます。
たとえば、FetchSizeをRowSize×10に設定すると、OracleDataReaderは各サーバー・ラウンドトリップごとにちょうど10行をフェッチします。RowSizeは、個々の列のデータ長によっては変化しません。RowSizeは、SELECTが実行されるデータベース表のメタデータ情報から厳密に決定されます。
RowSizeプロパティを使用して、設計時または実行時にFetchSize設定できます。それぞれのケースについて次に説明します。
特定のSELECT文に対する行サイズが過去の実行結果から明らかな場合、OracleCommandのFetchSizeを、その行サイズとアプリケーションが1回のサーバー・ラウンドトリップでフェッチする行数を掛けた値に設計時に設定できます。OracleCommandオブジェクトに設定されたFetchSizeの値は、OracleCommandへのExecuteReaderメソッドの起動によって作成されるOracleDataReaderに継承されます。OracleCommandオブジェクトにFetchSizeを設定するかわりに、OracleDataReaderに直接FetchSizeを設定することもできます。どちらの場合も、FetchSizeは設計時に設定され、実行時のRowSizeプロパティにはアクセスしません。
設計時に行サイズが明らかでないアプリケーションでは、OracleCommandオブジェクトのRowSizeプロパティを使用してOracleDataReaderオブジェクトのFetchSizeプロパティを設定できます。RowSizeプロパティにより、行のサイズに基づいてFetchSizeプロパティを動的に設定することができます。
OracleCommandにExecuteReaderメソッドが起動されてOracleDataReaderオブジェクトが取得されると、RowSizeプロパティに行のサイズ(バイト)が移入されます。このRowSizeプロパティを使用することにより、OracleDataReaderのFetchSizeプロパティを、RowSizeプロパティの値に1回のサーバー・ラウンドトリップでフェッチする行数を掛けた値に動的に設定することができます。この場合、FetchSizeは実行時のRowSizeプロパティにアクセスして設定されます。
OracleCommandオブジェクトは、Oracleデータベース上で実行されるSQL文またはストアド・プロシージャを表します。
この項では、次の項目について説明します。
Oracleデータベースでは、接続のコンテキストでのみトランザクションが開始されます。いったんトランザクションが開始されると、その接続での連続するすべてのコマンドはそのトランザクションのコンテキスト内で実行されます。トランザクションはOracleConnectionオブジェクトでのみ開始でき、OracleCommandオブジェクトに対する読取り専用のTransactionプロパティは、OracleConnectionオブジェクトによって暗黙的に設定されます。したがって、アプリケーションではTransactionプロパティを設定できず、またその必要もありません。
ODP.NETでは、アプリケーションはデータを.NET Framework型またはODP.NET型として取得できます。
データがどちらの形で取得されるかは、アプリケーションでOUTパラメータがOracleParameterのDbTypeプロパティ(.NET型)またはOracleDbTypeプロパティ(ODP.NET型)のどちらに設定されるかによって決まります。
たとえば、出力パラメータがDbType.Stringとしてバインドされている場合、出力データは.NET Stringとして返されます。逆にパラメータがOracleDbType.Charとしてバインドされている場合、出力データはOracleString型として返されます。
OracleParameterのDbTypeが設定されている場合、OracleParameterのOracleDbTypeはそれに応じて変更されます。またその逆も同様です。最後に設定されたパラメータが優先されます。
また、アプリケーションでは単にデータをバインドし、パラメータ値の.NET型からDbTypeとOracleDbTypeの両方をODP.NETに推論させることもできます。
ODP.NETでは、次のOracleCommandメソッドの実行により、InputOutput、OutputおよびReturnValueパラメータにOracleデータが移入されます。
アプリケーションで出力パラメータの値をバインドする必要はありません。ODP.NETにより値オブジェクトが作成され、OracleParameterのValueプロパティにそのオブジェクトが移入されます。
この項では、次の項目について説明します。
OracleDbType列挙値は、OracleParameterのOracleDbTypeを明示的に指定するために使用されます。
表3-5に、すべてのOracleDbType列挙値をリストし、各値について説明します。
この項では、OracleParameterクラス内のSystem.Data.DbType、OracleDbTypeおよびValueプロパティからの推論について説明します。
OracleParameterクラス内では、DbType、OracleDbTypeおよびValueプロパティはリンクされています。このいずれかのプロパティの値を指定すると、1つ以上の他のプロパティの値が推論されます。
OracleParameterクラス内で、OracleDbTypeの値を指定すると、表3-6に示されたDbTypeの値が推論されます。
OracleParameterクラス内で、DbTypeの値を指定すると、表3-7に示されたOracleDbTypeの値が推論されます。
OracleParameterクラス内で、Valueは、あらゆる.NET Frameworkデータ型またはODP.NET型にできるオブジェクト型です。OracleParameterオブジェクト内のOracleDbTypeおよびDbTypeが指定されていない場合、Valueプロパティの型からOracleDbTypeが推論されます。
表3-8に、Valueの型がいずれかの.NET Frameworkデータ型である場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。
表3-9に、Valueの型がいずれかのOracle.DataAccess.Typesである場合に、Valueから推論されるDbTypeおよびOracleDbTypeを示します。
ODP.NETは、PL/SQL連想配列(以前はPL/SQL索引付き表と呼ばれていた)のバインドをサポートします。
アプリケーションで、OracleParameterをPL/SQLストアド・プロシージャにPL/SQL連想配列としてバインドすることができます。この機能では、次のOracleParameterプロパティを使用します。
CollectionType
PL/SQL連想配列をバインドするためには、このプロパティをOracleCollectionType.PLSQLAssociativeArrayに設定する必要があります。
ArrayBindSize
固定長の要素型(Int32など)ではこのプロパティは無視されます。
可変長の要素型(Varchar2など)に対しては、ArrayBindSizeプロパティの各要素でValueプロパティの対応する要素のサイズを指定します。
Outputパラメータ、InputOutputパラメータおよび返り値の場合、可変長の変数に対してこのパラメータを設定する必要があります。
ArrayBindStatus
このプロパティでOracleParameter.Valueプロパティの各要素の実行ステータスを指定します。
Size
このプロパティで、PL/SQL連想配列にバインドする要素の最大数を指定します。
Value
このプロパティには値の配列を設定するか、nullまたはDBNull.Valueを設定します。
この例は、3つのOracleParameterオブジェクトをPL/SQL連想配列としてバインドしています。具体的には、Param1をInパラメータとして、Param2をInputOutputパラメータとして、Param3をOutputパラメータとしてバインドします。
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表に挿入します。OracleCommandのArrayBindCountプロパティにより、文の実行時に使用される配列の要素数が定義されます。
// 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オブジェクトでは、配列バインド機能を使用する際の粒度の制御のために2つのプロパティが提供されます。
ArrayBindSizeプロパティ
ArrayBindSizeプロパティは、配列内の対応する値ごとの最大サイズを指定する整数の配列です。ArrayBindSizeプロパティが配列内の値ごとのサイズを指定するという点以外は、ArrayBindSizeプロパティとOracleParameterのSizeプロパティは同じです。
実行前に、アプリケーションによってArrayBindSizeにデータが移入される必要があります。実行後は、ODP.NETによってArrayBindSizeにデータが移入されます。
ArrayBindSizeは、Clob、BlobおよびVarchar2などの可変長を持つパラメータの型にのみ使用されます。サイズは、バイナリ・データ型の場合はバイトで、Unicode文字列型の場合は文字で表されます。文字列型の場合、末尾の文字はカウントされません。サイズは、明示的に設定されていない場合は実際の値のサイズから推論されます。出力パラメータの場合、各値のサイズはODP.NETによって設定されます。固定長のデータ型の場合、ArrayBindSizeプロパティは無視されます。
ArrayBindStatusプロパティ
ArrayBindStatusプロパティは、パラメータに対する配列内の対応する値ごとのステータスを指定するOracleParameterStatus値の配列です。ArrayBindStatusプロパティは、配列内の値ごとのステータスを指定するという点以外は、OracleParameterのStatusプロパティと同じです。
実行前に、アプリケーションによってArrayBindStatusプロパティにデータが移入される必要があります。実行後には、ODP.NETによってこのプロパティにデータが移入されます。実行前に、ArrayBindStatusを使用するアプリケーションでは、パラメータに対する配列内の対応する要素にnull値を指定できます。実行後、ODP.NETによってArrayBindStatus配列にデータが移入され、配列内の対応する要素がnull値を持つか、値がフェッチされたときにデータの切捨てが行われたかが示されます。
配列バインドの実行中にエラーが発生した場合、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); }
表3-10に、OracleParameterStatus列挙体の様々な値を示します。
REF CURSORは、OracleのPL/SQL言語におけるデータ型です。これは、Oracleデータベース・サーバーでのカーソルまたは結果セットを表します。OracleRefCursorは、REF CURSOR型に対応するODP.NET型です。
この項では、REF CURSORおよびOracleRefCursorオブジェクトの使用方法に関する次の内容について説明します。
OracleRefCursorオブジェクトに対するコンストラクタはありません。コンストラクタは、PL/SQLストアド・プロシージャ、ストアド・ファンクションまたは無名ブロックからパラメータ値として取得できるだけです。
OracleRefCursorは接続オブジェクトです。OracleRefCursorオブジェクトを返すコマンドの実行に使用される接続は、その存続期間中は必要です。OracleRefCursorに関連付けられた接続がクローズされると、OracleRefCursorは使用できなくなります。
REF CURSORは、OracleDataReader、DataSetまたはOracleRefCursorとして取得できます。OracleRefCursorオブジェクトとして取得されたREF CURSORは、OracleDataReaderの作成またはREF CURSORからDataSetへの移入に使用できます。REF CURSORにアクセスする際は、必ずOracleDbType.RefCursorとしてバインドします。
OracleのREF CURSORは、OracleCommandのExecuteReaderメソッドをコールすることにより、OracleDataReaderとして取得できます。OracleDbTypeプロパティが設定された出力パラメータは、OracleDbType.RefCursorにバインドされます。ExecuteReaderのコール後に移入されるOracleDbType.RefCursor型の出力パラメータはありません。
複数の出力REF CURSORパラメータがある場合は、OracleDataReaderのNextResultメソッドを使用して次のREF CURSORにアクセスします。OracleDataReaderのNextResultメソッドでは、REF CURSORへの順次アクセスを提供します。つまり、一度に1つのREF CURSORにしかアクセスできません。
OracleDataReaderオブジェクトが対応するREF CURSORに対して作成される順序は、パラメータがバインドされる順序によって決まります。PL/SQLストアド・ファンクションによりREF CURSORが返された場合、これが最初のOracleDataReaderになり、すべての出力REF CURSORオブジェクトは、パラメータがバインドされる順序に従います。
FillメソッドによりDataSetプロパティへの移入が適切に行われるためには、OracleDataAdapterのSelectCommandが、OracleDbType.RefCursor型の出力パラメータでバインドされている必要があります。Fillメソッドが正常に実行されると、DataSetにREF CURSORを表すDataTableが移入されます。
コマンド実行により複数のREF CURSORが返された場合、DataSetに複数のDataTableが移入されます。
1つ以上のREF CURSORを返すコマンドでExecuteNonQueryが起動されると、OracleDbType.RefCursorとしてバインドされているOracleCommandパラメータそれぞれがOracleRefCursorオブジェクトへの参照を取得します。
OracleRefCursorオブジェクトからOracleDataReaderを作成するには、OracleRefCursorオブジェクトからGetDataReaderをコールします。それ以降にGetDataReaderをコールすると、同じOracleDataReaderへの参照が返されます。
DataSetにOracleRefCursorオブジェクトを移入する場合、アプリケーションでは、OracleRefCursorオブジェクトをとるOracleDataAdapterのFillメソッドをコールできます。
コマンド実行によって複数のREF CURSORがOracleRefCursorオブジェクトとして返された場合、アプリケーションでは、OracleDataReaderを作成するか、DataSetに特定のOracleRefCursorオブジェクトを移入するかを選択できます。OracleRefCursorから作成されたすべてのOracleDataReaderまたはDataSetは同時にアクティブになり、任意の順序でアクセスできます。
REF CURSORは更新可能ではありません。ただし、DataSet内に取得されたデータは更新可能です。このため、OracleDataAdapterでは、データベースにREF CURSORデータの更新をフラッシュするためのカスタムSQL文が必要です。
REF CURSOR更新用のSQLを生成するためにOracleCommandBuilderは使用できません。
ExecuteScalarは、ストアド・ファンクションの戻り値か、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータを返します。このため、REF CURSORがストアド・ファンクションの戻り値でも、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータでもない場合、REF CURSORはExecuteScalarに無視されます。
しかし、REF CURSORがストアド・ファンクションの戻り値か、ストアド・プロシージャまたは無名PL/SQLブロックの最初のバインド・パラメータである場合は、REF CURSOR内の最初の行の最初の列の値が返されます。
ODP.NETには、ラージ・オブジェクト・データ型にアクセスおよび操作するための簡単で最適な方法があります。Oracleでは、文字データおよびバイナリ・データのLOBデータ型がサポートされています。
ODP.NETでは、LOBデータを操作するための、OracleBFile、OracleBlobおよびOracleClobというの3つのLOB用オブジェクトが提供されます。
表3-11に、特定のOracle LOB型に使用する適切なODP.NETクラスを示します。
| Oracle LOB型 | ODP.NET LOBオブジェクト |
|---|---|
|
|
OracleBFileオブジェクト |
|
|
OracleBlobオブジェクト |
|
|
OracleClobオブジェクト |
|
|
OracleClobオブジェクト |
ODP.NET LOBオブジェクトは、OracleDataReaderで適切な型指定のアクセッサをコールして取得するか、または適切なバインド型を使用したコマンド実行で出力パラメータとして取得することができます。
すべてのODP.NET LOBオブジェクトは、.NETのStreamクラスから継承され、汎用Stream操作を可能にします。LOBデータ(BFILEを除く)は、Writeなどのメソッドを使用することによって、ODP.NET LOBオブジェクトを使用した更新が可能になります。読取り/書込み操作が行われる際、データはLOBオブジェクト内にキャッシュされません。このため、ReadまたはWriteが要求されるたびに、サーバー・ラウンドトリップが発生します。OracleClobはReadメソッドをオーバーロードし、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ではコマンドの実行時に例外が呼び出されます。
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オブジェクトを使用する必要があります。
LOB列を更新する場合、LOBデータを、SQL文、無名PL/SQLブロックまたはストアド・プロシージャのパラメータとしてバインドできます。パラメータ値は、NET Framework型、ODP.NET型またはODP.NET LOBオブジェクト型として設定できます。たとえば、.NET文字列データをOracle9iデータベース内のLOB列に挿入する場合、そのパラメータをOracleDbType.Varchar2としてバインドできます。値がOracleClobオブジェクトに設定されているパラメータの場合は、パラメータをOracleDbType.Clobとしてバインドする必要があります。
OracleのBFILEは更新不可能なので、OracleBFileオブジェクトではBFILE列の更新は許可されません。
ODP.NET LOBオブジェクトを使用してLOBデータを更新するには、次の2つの要件を満たしている必要があります。
OracleTransactionのCommitまたはRollbackの起動時にロックを解放できるように、OracleCommandの実行前にこのコマンドのBeginTransactionメソッドを使用してトランザクションが開始されている必要があります。
BLOB、CLOBおよびNCLOBに対して、一時LOBをインスタンス化できます。一時LOBを表すODP.NET LOBオブジェクトをインスタンス化するには、OracleClobまたはOracleBlobコンストラクタを使用できます。
一時ODP.NET LOBオブジェクトは、次のような場合に使用できます。
CopyTo操作で行うのと同様に、2つのLOBオブジェクト間でデータを転送する際のソースまたは宛先として使用する場合
ODP.NETのグローバリゼーション・サポートによって、アプリケーションで、文化によって異なるデータを適切に操作できます。この機能を使用すると、Oracleグローバリゼーション設定に従って適切な文字列フォーマット、日付、時刻、通貨、数値、ソート順序およびカレンダ規則が適用されます。
この項では、次の項目について説明します。
OracleGlobalizationオブジェクトを使用して、次の設定を表すことができます。
クライアント・グローバリゼーション設定は、ローカル・コンピュータのWindowsレジストリ内のOracleグローバリゼーション設定(NLS_LANG)から導出されます。クライアント・グローバリゼーション・パラメータ設定は読取り専用であり、アプリケーションの存続期間中は変わりません。クライアント・グローバリゼーション設定は、OracleGlobalization.GetClientInfo() staticメソッドをコールすることにより取得できます。
次の例では、クライアント・グローバリゼーション設定を取得しています。
// C# ... // GetClientInfo() is a static method on OracleGlobalization class OracleGlobalization ClientGlob = OracleGlobalization.GetClientInfo();
OracleGlobalizationオブジェクトのプロパティにより、Oracleグローバリゼーション値が設定されます。
セッション・グローバリゼーション・パラメータは、最初はクライアント・グローバリゼーション設定と同じです。クライアント設定とは異なり、セッション・グローバリゼーション設定は更新可能です。ただし、セッション・グローバリゼーション設定はデータベース・サーバーへの接続を確立した後でしか取得できません。セッション・グローバリゼーション設定は、OracleConnectionのGetSessionInfo()をコールすることにより取得できます。このメソッドをコールすると、セッションのグローバリゼーション設定を表すプロパティを持つ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設定が使用されます。
次のコードでは、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オブジェクトの他のプロパティが暗黙的に変更されますので注意してください。
この項では、グローバリゼーション設定に依存する、またはこの設定の影響を受ける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型メソッドに関する備考を読み、その特定のメソッドに対して使用されるスレッド・グローバリゼーション設定を確認してください。
セッション・グローバリゼーション設定は、文字列としてサーバーから取得される、またはサーバーに送信されるすべてのデータに影響を与えます。
たとえば、TO_CHAR()関数が適用されたDATE列が選択されている場合、DATE列のデータは、セッション・グローバリゼーション設定のDateFormatで指定された日付書式の文字列になります。逆の方向にデータを送信するには、DATE列に挿入する文字列データを、セッション・グローバリゼーション設定のDateFormatプロパティで指定された書式にする必要があります。
また、セッション・グローバリゼーション設定は、安全な型マッピングを使用して文字列としてDataSet内に取得されるデータにも影響を与えます。型の書式が区別される場合、文字列は常に、セッション・グローバリゼーション設定で指定されている書式になります。
たとえば、VARCHAR2およびCHARデータは、適用可能な書式がないため、セッション設定の影響を受けません。しかし、DateFormatおよびNumericCharactersプロパティは、DATE型とNUMBER型が安全な型マッピングを使用してデータベース・サーバーから文字列として取得された場合、それぞれの文字列表現に影響を与える可能性があります。
この項では、DataTableのPrimaryKeyおよびConstraintsプロパティがどのようにOracleDataAdapterによって構成されるかについて説明します。この2つのプロパティは、OracleCommandBuilderでDataSetの変更内容がデータベースへ更新される際の一意性を保証します。
データベースに対して実行される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の一意性を保証するための最低条件について説明します。次の項で説明する方法でDataTable.PrimaryKeyプロパティおよびDataTable.Constraintsプロパティを設定する前に、一意性の条件を確保しておく必要があります。
次のうち1つでも当てはまればDataTableにおける一意性が保証されます。
OracleDataAdapter.SelectCommandの選択リストに含まれている。
OracleDataAdapter.SelectCommandの選択リストに含まれ、少なくとも1つの列にNOT NULL制約が定義されている。
OracleDataAdapter.SelectCommandの選択リストに含まれ、少なくとも1つの列にNOT NULL制約が定義されている。
OracleDataAdapter.SelectCommandの選択リストにROWIDが含まれている。
「DataRowの一意性を構成する要素」に説明した最低条件を満たしていれば、DataTable.PrimaryKeyまたはDataTable.Constraintsプロパティを設定できます。
これらのプロパティが設定されると、OracleCommandBuilderではDataTable.PrimaryKeyプロパティの設定またはDataTable.ConstraintsコレクションにおけるDataTable.Constraintの有無によってDataTableにおける一意性を判断できます。一意性が確認されれば、OracleCommandBuilderでは更新を実行するDML文を安全に生成できます。
OracleDataAdapter.FillSchemaメソッドは、これらのプロパティの設定を次の優先順位で試みます。
DataTable.PrimaryKeyとして設定されます。
DataTable.PrimaryKeyとして設定されます。
条件: 列セットに一意制約が定義されているかまたは一意のインデックスが作成されていて、各列にNOT NULL制約が定義されている場合。
DataTable.ConstraintsコレクションにUniqueConstraintが追加され、DataTable.PrimaryKeyは設定されません。
条件: 列セットに一意制約が定義されているかまたは一意のインデックスが作成されていて、少なくとも1つの列にNOT NULL制約が定義されている場合。
ROWIDが含まれる場合、それがDataTable.PrimaryKeyとして設定されます。
その他にも、OracleDataAdapter.FillSchemaは次の処理を行います。
アプリケーションがOracleDataAdapter.FillSchemaをコールしていないといった理由でDataTable.PrimaryKeyまたはConstraintsプロパティが設定されていない場合、OracleCommandBuilderがOracleDataAdapter.SelectCommandの選択リストを直接チェックしてDataTableにおける一意性を判断します。ただしこのチェックでは、OracleDataAdapter.SelectCommandのSELECT文に対するメタデータを取得するためにサーバー・ラウンドトリップが発生します。
PL/SQL文のメタデータにはキー情報が返されないため、OracleCommandBuilderではPL/SQL文から作成されたDataTableは更新できません。
次のOracleデータ型は、密接に関連する.NET型に変換される際にデータが失われる可能性があるため、ODP.NETのOracleDataAdapterでは安全な型マッピング機能が提供されます。
これらいずれかの型を含むOracleデータを.NET DataSetに移入すると、データが失われる可能性があります。OracleDataAdapterの安全な型マッピング機能を使用すると、データは失われません。SafeMappingプロパティを適切に設定することにより、これらの型を次のいずれかとしてDataSet内で確実に表すことができます。
次の各項では、データが失われる可能性のある型および状況について詳しく説明します。
Oracleのデータ型NUMBERは最大38精度を保持できますが、.NETのDecimal型は最大28精度しか保持できません。28精度を超えるNUMBERデータ型が.NETのDecimal型内に取得されると、精度が失われます。
表3-12に、OracleのNUMBERおよび.NETのDecimalの最大値と最小値をリストします。
Oracleのデータ型DATEではBCの日付を表すことができますが、.NETのDateTimeでは表すことができません。BCを使用する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 |
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の最大値と最小値をリストします。
| 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 |
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の最大値と最小値をリストします。
| 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 |
デフォルトでは、安全な型マッピングは使用不可になっています。
安全な型マッピング機能を使用するには、OracleDataAdapter.SafeMappingプロパティを、キーと値のペアのハッシュテーブルで設定する必要があります。このキーと値のペアで、データベース表の列名(型string)を.NET型(型Type)にマップする必要があります。ODP.NETでは、byte[]およびString型への安全な型マッピングがサポートされています。これ以外の型マッピングを行うと、例外が発生します。
設計時に列名が不明な場合は、必要に応じてアスタリスク(*)を使用し、データベース型のすべてのデータを安全な.NET型にマップできます。有効な列名とアスタリスクの両方がある場合、列名が使用されます。
文字列としての安全な型マッピングは、読み込みやすく、追加の変換が必要ありません。特定のOracleデータ型を文字列に変換するには、追加の変換を行う必要があります。この変換は、byte[]への変換よりも時間がかかる可能性があります。.NETの文字列をODP.NET型に戻す変換は、セッションの書式設定情報に基づいて行われます。
OracleDataAdapterのRequeryプロパティにより、OracleDataAdapterのFillコールに対して、最初のFillコールの後で問合せを再実行するかどうかを制御します。
OracleDataAdapterのFillメソッドを使用すると、DataSet内のデータを追加またはリフレッシュできます。それ以降のFillコールで同じ問合せを使用してDataSetを追加する場合は、問合せを再実行しないほうがよい場合があります。
Requeryプロパティがtrueに設定されている場合、それ以降のFillコールによって問合せが再実行され、DataSetにデータが埋め込まれます。これは負荷がかかる操作なので、再実行が必要でなければ、Requeryはfalseに設定してください。SelectCommandプロパティまたは関連するパラメータのいずれかを変更する必要がある場合は、Requeryをtrueに設定してください。
Requeryプロパティがfalseに設定されている場合、DataSetにはある時点のスナップショットとしてのデータ全体が含まれます。問合せは最初のFillコールに対してのみ実行され、それ以降のFillコールでは、問合せの最初の実行でオープンされたカーソルからデータがフェッチされます。この機能がサポートされるのは、順方向専用のフェッチについてのみです。Fillコールで、最後にフェッチされた行より前の行をフェッチしようとすると、例外が呼び出されます。最初のFillコールに使用された接続は、それ以降のFillコールに対しても使用可能である必要があります。
DataSetにOracleRefCursorを埋め込む際も、同様の方法でRequeryプロパティを使用できます。Requeryプロパティをfalseに設定すると、最初のFillに使用された接続とOracleRefCursorの両方が、それ以降のFillコールに対して使用可能である必要があります。
ODP.NETでは、すべてのODP.NETアクティビティをトレース・ファイルにロギングできるデバッグ・トレースがサポートされています。様々なレベルのトレースが可能です。
プロバイダでは、次の情報を記録できます。
後述のレジストリ設定は、次のディレクトリの下に構成してください。
HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET
TraceFileNameの有効な値は、任意の有効なパスおよびファイル名です。
TraceFileNameでは、トレース情報のロギングに使用されるファイル名を指定します。TraceOptionが0に設定されている場合、名前がそのまま使用されます。しかし、TraceOptionが1の場合、指定されたファイル名にスレッドIDが追加されます。
TraceLevelの有効な値は、次のとおりです。
TraceLevelでは、ODP.NETでのトレース・レベルを指定します。すべてのオブジェクトに対する入力コールと出力コールすべてをトレースすると負荷がかかるため、TraceLevelを指定して、トレースをプロバイダの特定の領域に制限します。
複数のオブジェクトについてのトレースを取得するには、有効な値を追加するだけです。たとえば、TraceLevelが3に設定されている場合、トレース情報は入力、出力、SQLおよび接続プーリング情報についてロギングされます。
TraceOptionの有効な値は、次のとおりです。
TraceOptionでは、各スレッドIDについてトレース情報を1つのファイルにロギングするか複数のファイルにロギングするかを指定します。1つのトレース・ファイルを指定した場合、TraceFileName内に指定されているファイル名が使用されます。複数のトレース・ファイル・オプションを要求した場合、スレッドごとにトレース・ファイルを作成するために、指定されているファイル名にスレッドIDが追加されます。
Oracle8iリリース8.1.7以降、Oracleではリレーショナルまたはオブジェクト・リレーショナルの表およびビューからデータをXML文書として抽出できます。データベース・サーバーに対する挿入、更新および削除操作にXML文書を使用することも可能です。
Oracle9iリリース2(9.2)では、高パフォーマンスなXMLの格納と取得に関連した特定のテクノロジ群であるOracle XMLデータベースによって、XMLがデータベース内でネイティブにサポートされます。Oracle XMLデータベースは、SQLとXML双方のデータ・モデルを取り入れて高次元の相互操作を可能にしたOracleの発展形で、ネイティブなXMLサポートを提供します。
ODP.NETのXMLサポートに関連したサンプルは、次のディレクトリに用意されています。
%ORACLE_HOME%\ODP.NET\Samples
この項では、次の項目について説明します。
ODP.NETでは次のXML機能がサポートされます。
XMLTypeとしてデータベース・サーバーにそのまま格納します。
.NETアプリケーションの開発者が利用できる具体的な機能は次のとおりです。
OracleCommand、OracleConnectionおよびOracleDataReaderクラスに対する拡張
OracleXmlTypeクラス
OracleXmlTypeオブジェクトを使用して、Oracle固有のXMLTypeデータを取得します。
OracleXmlStreamクラス
OracleXmlStreamオブジェクトを使用して、読取り専用の.NET StreamオブジェクトとしてOracleXmlTypeオブジェクトからXMLデータを取得します。
OracleXmlQueryPropertiesクラス
OracleXmlQueryPropertiesオブジェクトは、XmlCommandTypeプロパティがQueryのときにOracleCommandクラスによって使用されるXMLプロパティを表します。
OracleXmlSavePropertiesクラス
OracleXmlSavePropertiesオブジェクトは、XmlCommandTypeプロパティがInsert、UpdateまたはDeleteのときにOracleCommandクラスによって使用されるXMLプロパティを表します。
| 関連資料:
|
OracleXmlTypeオブジェクトの読取り専用のConnectionプロパティには、OracleXmlTypeオブジェクトのインスタンス化に使用されたOracleConnectionオブジェクトへの参照が格納されます。
OracleXmlTypeオブジェクトがOracleConnectionオブジェクトへの参照を取得する方法は、OracleXmlTypeオブジェクトがどのようにインスタンス化されたかによって決まります。
GetOracleXmlType、GetOracleValueまたはGetOracleValuesメソッドを使用してOracleDataReaderからインスタンス化された場合
Connectionプロパティには、OracleDataReaderで使用されたのと同じOracleConnectionオブジェクトへの参照が設定されます。
OracleConnection型のいずれかのパラメータを指定したOracleXmlTypeコンストラクタを起動してインスタンス化された場合
Connectionプロパティには、コンストラクタに指定されたのと同じOracleConnectionオブジェクトへの参照が設定されます。
OracleXmlType(OracleClob)コンストラクタを起動してインスタンス化された場合
Connectionプロパティには、OracleClobで使用されたのと同じOracleConnectionオブジェクトへの参照が設定されます。
ある接続に関連付けられたOracleXmlTypeオブジェクトは、別の接続では使用できません。たとえば、あるOracleXmlTypeオブジェクトをOracleConnection Aを使用して取得した場合、そのオブジェクトはOracleConnection Bを使用するコマンドの入力パラメータには使用できません。OracleXmlTypeオブジェクトのConnectionプロパティをチェックすれば、OracleXmlTypeオブジェクトがその接続プロパティで参照しているOracleConnectionのコンテキスト内でのみ使用されていることをアプリケーションで確認できます。そうでない場合、ODP.NETでは例外が呼び出されます。
XMLType列の更新にはトランザクションは必要ありません。ただし、データベースの更新処理全体をトランザクションにカプセル化することを強くお薦めします。そうすれば、エラーが発生したときでも更新をロールバックできます。
データベース内のXMLType列は、Oracle Data Provider for .NETを使用していくつかの方法で更新できます。
XMLType列がDataSetにフェッチされている場合、XMLTypeデータは.NET Stringとして表されます。
DataSet内のXMLTypeデータの更新には特別な操作は必要ありません。XMLTypeデータは、DataSetに格納されている他のデータと同じ方法で変更できます。変更が行われてOracleDataAdapter.Update()が起動されると、OracleDataAdapterがXMLTypeデータを適切に処理します。OracleDataAdapterは、提供されたあらゆるカスタムのSQL INSERT、UPDATEまたはDELETE文を使用します。または、データベース・サーバーに変更をフラッシュするために必要な有効なSQL文がOracleCommandBuilderによって生成されます。
OracleCommandは、特にOracleParameterを使用した場合にXMLTypeデータの更新に威力を発揮します。データベース表の列を更新するには、新しい値をコマンドの入力パラメータとして渡すことができます。
データベース内のXMLType列を更新するには、静的な値を使用してSQL文を実行できます。さらに、SQL文、無名PL/SQLブロックまたはストアド・プロシージャに入力パラメータをバインドしてXMLType列を更新できます。パラメータ値は.NET Framework型、ODP.NET型またはOracleXmlTypeオブジェクトとして設定できます。
XMLType列はOracleXmlTypeオブジェクトを使用して更新できますが、OracleXmlTypeオブジェクトのインスタンスがあるからといってデータベース内のXMLType列を更新できるとは限りません。
アプリケーションでデータベース内のXmlType列をnull値に設定できます。入力バインドを使用する方法と使用しない方法があります。
XmlType列にnull値を設定する方法
XmlType列をnull値に設定するには、値がDBNull.Valueの入力パラメータをバインドします。これで、null値を挿入するようOracleCommandに対して指示されます。
nullのOracleXmlTypeオブジェクトを入力パラメータとして渡しても、XmlType列にnull値は挿入されません。この場合、OracleCommandによって例外が呼び出されます。
XmlType列にnull値を設定する方法
次の例は、入力バインドを使用せずにXmlType列にnull値を設定する方法を示しています。
// Create a table with an XMLType column in the database CREATE TABLE XMLTABLE(NUM_COL number, XMLTYPE_COL xmltype);
アプリケーションでは、次の例のように明示的にnull値を挿入するか、何も挿入しないことで、XmlType列にnull値を設定できます。
insert into xml_table(xmltype_col) values(NULL); update xml_table t set t.xmltype_col=NULL;
// Create a table with an XMLType column in the database CREATE TABLE XMLTABLE(NUM_COL number, XMLTYPE_COL xmltype); INSERT INTO XML_TABLE (NUM_COL, XMLTYPE_COL) VALUES (4, XMLType.createxml('<DOC/>'));
OracleXmlTypeオブジェクトでXMLデータを更新する方法はいくつかあります。
OracleXmlTypeオブジェクトに対するUpdateメソッドにXPath式と新しい値を渡してXMLデータを更新できます。
OracleXmlTypeオブジェクトに対するGetXmlDocumentメソッドを使用して、.NET FrameworkのXmlDocumentオブジェクトとしてXMLデータを取得できます。取得したXMLデータは、該当する.NET Frameworkクラスを使用して操作できます。.NET Frameworkクラスから、更新されたXMLデータでOracleXmlTypeを新たに作成できます。作成されたOracleXmlTypeは、更新または挿入文への入力パラメータとしてバインドされます。
次の文字はXMLでは特別な意味を持ちます。詳細は、XML 1.0の仕様書を参照してください。
| 特殊文字 | XMLでの意味 | エンティティ・コード |
|---|---|---|
|
< |
XMLタグの開始 |
< |
|
> |
XMLタグの終了 |
> |
|
" |
引用符 |
" |
|
|
アポストロフィまたは一重引用符 |
' |
|
& |
アンパサンド |
& |
これらの文字がXML要素にデータとして出現した場合、該当するエンティティ・コードに置き換えられます。
また、特定の文字はXML要素名には使用できません。SQL識別子(列名など)がXML要素名にマッピングされる際、該当する文字はUnicodeのエンコードに基づく16進数の先頭にアンダースコアと小文字のX、末尾にアンダースコアを加えた文字列に変換されます。たとえば、スペースはXML要素名には使用できません。SQL識別子にスペースが含まれていた場合、対応するXML要素名では、スペースのUnicodeエンコードに基づいて該当箇所が_x0020_に置き換えられます。
この項では、SQL問合せの結果セットをXMLデータとして取得する方法について説明します。
表3-17に、日付および時刻書式の処理をデータベースのリリース別に記載します。
問合せ内の選択リスト列に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><Jones></NAME> </ROW> </ROWSET>
表またはビューの名前にアンダースコア(_)以外の非英数字が含まれる場合、表名またはビュー名を引用符で囲みます。
たとえば、test'ingという名前の表からすべてのエントリを選択するには、OracleCommandオブジェクトのCommandTextプロパティを次の文字列に設定します。
"select * from \"test'ing\"";
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列に対する要素名では、列名と同じように大文字/小文字が区別されています。
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のデータベースから問合せ結果をXMLとして取得する場合、問合せ選択リスト内のSQL識別子には、XML要素名に無効な文字を使用できません。Oracle8iリリース8.1.7ではこの問題に対処するサポートがないため、次の例のようなSQL問合せを使用してspecialchars表から結果をXML文書として取得します。
select "some id" as "some_x0020_id", name from specialchars;
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値の列があった場合、生成されるXML文書ではその行に対してnull値の列は含まれません。
この項では、XMLを使用してデータベースに変更を加える方法について説明します。
表3-18に、日付および時刻書式の処理をデータベースのリリース別に記載します。
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><Jones></NAME> </ROW> </ROWSET>
表またはビューの名前にアンダースコア(_)以外の非英数字が含まれる場合、表名またはビュー名を引用符で囲みます。
たとえば、test'ingという名前の表に変更を保存するには、OracleCommand.XmlSaveProperties.TableNameプロパティを"\"test'ing\""に設定します。
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列に対する要素名では、列名と同じように大文字/小文字が区別されています。
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データベースで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><Jones></NAME> </ROW> </ROWSET>
specialchars表にview2を使用して値(1, <Jones>)を挿入するには、次のXML文書を使用できます。
<?xml version = '1.0'?> <ROWSET> <ROW> <SOMEID>2</SOMEID> <NAME><Jones></NAME> </ROW> </ROWSET>
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><Jones></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では、結合された複数のリレーショナル表へ変更を保存することはできません。この場合、該当するリレーショナル表に対してビューを作成し、そのビューを更新することをお薦めします。ビューが更新できない場合には、かわりにトリガーを使用できます。
XML文書が変更されると、すべての変更がコミットされるか、またはエラーが発生した場合にはすべての変更がロールバックされます。
|
|
![]() Copyright © 2002, 2003 Oracle Corporation. All Rights Reserved. |
|