3.8 OracleCommandオブジェクト
OracleCommand
オブジェクトは、Oracle Databaseで実行されるSQL文またはストアド・プロシージャを表します。
注意:
オプティマイザのヒント構文形式--+ ...
はサポートされていません。ODP.NETでは、/*+ ... */
の構文をサポートしています。
この項の内容は次のとおりです。
3.8.1 トランザクション
Oracle Databaseは、接続のコンテキストでのみトランザクションを開始します。トランザクションが開始すると、その接続で引き続き行われるコマンド実行はすべて、そのトランザクションのコンテキストで実行されます。トランザクションはOracleConnection
オブジェクトでのみ開始され、OracleCommand
オブジェクトのTransaction
読取り専用プロパティは、OracleConnection
オブジェクトによって暗黙的に設定されます。このため、アプリケーションはTransaction
プロパティを設定できません。また、設定する必要もありません。
注意:
トランザクションは、.NETストアド・プロシージャではサポートされません。
"FOR
UPDATE"
および"RETURNING"
句を含むSQL文には明示的なトランザクションが必要です。グローバル・トランザクションが使用されていない場合は不要です。
3.8.2 System.TransactionsとPromotable Transaction
ODP.NETはSystem.Transactions
をサポートします。Oracle Database 11gリリース(11.1)以上のSystem.Transactions
スコープでオープンされた最初の接続に対しては、ローカル・トランザクションが作成されます。2番目の接続がオープンされると、このトランザクションは自動的に分散トランザクションに昇格します。この機能は、パフォーマンスとスケーラビリティの向上を実現します。
TransactionScope
やServicedComponent
などのトランザクション・コンテキスト内で作成された接続は、様々なリリースのOracle Databaseに対して確立できます。ただし、ローカル・トランザクションを昇格できるようにするには、次の条件を満たす必要があります。
-
Oracle Database 11gリリース1(11.1)以上のインスタンスに対してトランザクション・コンテキストの最初の接続を確立する必要があります。
-
トランザクション・コンテキスト内でオープンになっているすべての接続の
"Promotable Transaction"
設定が"promotable"
に設定されている必要があります。"Promotable Transaction"
設定が"local"
に設定されている場合、同じトランザクション・コンテキスト内にある後続の接続をオープンしようとすると、例外がスローされます。 -
ローカル・トランザクションの昇格には11.1.0.7.20以上のOracle Services for Microsoft Transaction Serverが必要です。この要件を満たしていない場合、同じトランザクション・コンテキスト内にある2番目の接続要求で例外がスローされます。
データベースのトランザクションがすでに分散されているときにトランザクションを昇格すると、データベース・リンクの使用によりORA-24797エラーがスローされます。
レジストリ、構成ファイル(マシン、Web、アプリケーション)または"PromotableTransaction"
接続文字列属性で、"Promotable Transaction"
の値として"local"
を設定すると、ローカル・トランザクションに関連付けられているトランザクション・コンテキスト内でオープンできる接続は1つのみになります。このようなローカル・トランザクションは昇格できません。ODP.NET 12.1.0.2以降、Promotable Transaction
設定をlocal
に設定した接続はローカル・トランザクションとして開始され、ローカル・トランザクションのままになります。トランザクションに加わるために2回目の接続を試みると、例外がスローされます。
アプリケーションがSystem.Transactions
を使用する場合は、enlist
接続文字列属性をtrue
(デフォルト)またはdynamic
のいずれかに設定する必要があります。ただし、自動登録するにはenlist=true
である必要があるため、TransactionScope
とともにenlist=dynamic
を使用することはできません。
ODP.NETは、分散トランザクションを使用するアプリケーション用に、次のSystem.Transactions
プログラミング・モデルをサポートしています。
関連項目:
Oracle Database 11gリリース1(11.1)より前のインスタンスに接続するアプリケーションについては、旧リリースのデータベースにおけるローカル・トランザクション・サポートを参照してください。この項では、Promotable Transactionの設定を使用してODP.NETの動作を制御する方法について説明します。
3.8.2.1 TransactionScopeを使用した暗黙的なトランザクション登録
TransactionScope
クラスは、トランザクションに明示的に登録する必要のないトランザクション・アプリケーションを記述するためのメカニズムを提供します。これを実現するには、アプリケーションでTransactionScope
オブジェクトを使用して、トランザクション・コードを定義します。このトランザクション・スコープ内で作成された接続は、分散トランザクションへの昇格が可能なローカル・トランザクションに登録されます。
注意:
デフォルトでは、最初の接続がOracle Database 11gリリース1(11.1)より前のインスタンスに対してオープンされた場合、その接続は分散トランザクションとして登録されます。
旧リリースのデータベースにおけるローカル・トランザクション・サポート」で説明する手順を使用して、トランザクションをローカル・トランザクションとして作成することも可能です。ただし、その場合のトランザクションは分散トランザクションに昇格できません。
変更をコミットするには、アプリケーションでTransactionScope
オブジェクトに対してComplete
メソッドをコールする必要があります。コールしない場合、トランザクションはデフォルトで強制終了します。
// C# using System; using Oracle.DataAccess.Client; using System.Data; using System.Data.Common; using System.Transactions; class psfTxnScope { static void Main() { int retVal = 0; string providerName = "Oracle.DataAccess.Client"; string constr = @"User Id=scott;Password=tiger;Data Source=oracle;enlist=true"; // Get the provider factory. DbProviderFactory factory = DbProviderFactories.GetFactory(providerName); try { // Create a TransactionScope object, (It will start an ambient // transaction automatically). using (TransactionScope scope = new TransactionScope()) { // Create first connection object. using (DbConnection conn1 = factory.CreateConnection()) { // Set connection string and open the connection. this connection // will be automatically enlisted in a promotable local transaction. conn1.ConnectionString = constr; conn1.Open(); // Create a command to execute the sql statement. DbCommand cmd1 = factory.CreateCommand(); cmd1.Connection = conn1; cmd1.CommandText = @"insert into emp (empno, ename, job) values (1234, 'emp1', 'dev1')"; // Execute the SQL statement to insert one row in DB. retVal = cmd1.ExecuteNonQuery(); Console.WriteLine("Rows to be affected by cmd1: {0}", retVal); // Close the connection and dispose the command object. conn1.Close(); conn1.Dispose(); cmd1.Dispose(); } // The Complete method commits the transaction. If an exception has // been thrown or Complete is not called then the transaction is // rolled back. scope.Complete(); } } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } }
3.8.2.2 CommittableTransactionを使用した明示的なトランザクション登録
CommittableTransaction
オブジェクトとEnlistTransaction
メソッドのインスタンス化により、接続を明示的に作成してトランザクションに登録できます。アプリケーションでは、CommittableTransaction
オブジェクトに対してCommit
またはRollback
をコールする必要があります。
// C# using System; using Oracle.DataAccess.Client; using System.Data; using System.Data.Common; using System.Transactions; class psfEnlistTransaction { static void Main() { int retVal = 0; string providerName = "Oracle.DataAccess.Client"; string constr = @"User Id=scott;Password=tiger;Data Source=oracle;enlist=dynamic"; // Get the provider factory. DbProviderFactory factory = DbProviderFactories.GetFactory(providerName); try { // Create a committable transaction object. CommittableTransaction cmtTx = new CommittableTransaction(); // Open a connection to the DB. DbConnection conn1 = factory.CreateConnection(); conn1.ConnectionString = constr; conn1.Open(); // enlist the connection with the commitable transaction. conn1.EnlistTransaction(cmtTx); // Create a command to execute the sql statement. DbCommand cmd1 = factory.CreateCommand(); cmd1.Connection = conn1; cmd1.CommandText = @"insert into emp (empno, ename, job) values (1234, 'emp1', 'dev1')"; // Execute the SQL statement to insert one row in DB. retVal = cmd1.ExecuteNonQuery(); Console.WriteLine("Rows to be affected by cmd1: {0}", retVal); // commit/rollback the transaction. cmtTx.Commit(); // commits the txn. //cmtTx.Rollback(); // rolls back the txn. // close and dispose the connection conn1.Close(); conn1.Dispose(); cmd1.Dispose(); } catch (Exception ex) { Console.WriteLine(ex.Message); Console.WriteLine(ex.StackTrace); } } }
関連項目:
3.8.2.3 旧リリースのデータベースにおけるローカル・トランザクション・サポート
TransactionScope
内の最初の接続がOracle Database 11gリリース1(11.1)より前のインスタンスに対してオープンされた場合、デフォルトでは分散トランザクションが作成されます。この項で説明する手順を使用すれば、最初の接続でローカル・トランザクションを作成することもできます。
System.Transactions
スコープ内にローカル・トランザクションを作成するには、レジストリ、マシン/Web/アプリケーション構成ファイルまたは"Promotable Transaction"
接続文字列属性のPromotableTransaction
設定を"local"
に設定します。
"local"
が指定されている場合、TransactionScope
でオープンした最初の接続ではローカル・トランザクションが使用されます。後続の接続が同じTransactionScope
でオープンされると例外がスローされます。TransactionScope
ですでに接続がオープンしていて、"Promotable Transaction=local"
のOracleConnection
が同じTransactionScope
内でオープンされようとしている場合は例外がスローされます。
"promotable"
が指定されている場合、同じTransactionScope
でオープンされる最初と後続の接続は、同じ分散トランザクション内で登録されます。
レジストリと接続文字列属性の両方が使用されていて異なる値に設定されている場合、接続文字列属性はレジストリ・エントリの値をオーバーライドします。どちらも設定されていない場合は"promotable"
が使用されます。これはデフォルトの値で、分散トランザクションのみがサポートされているODP.NETの以前のバージョンと同じです。
ODP.NETの特定のバージョンに対するレジストリ・エントリは、ODP.NETのバージョンを使用するすべてのアプリケーションに適用します。
3.8.3 パラメータ・バインド
OracleParameter
オブジェクトのDbType
プロパティが設定されている場合、OracleParameter
オブジェクトのOracleDbType
プロパティも変更されます。その逆も同じです。パラメータ・セットは最後に有効になります。アプリケーションはデータをバインドして、パラメータ値の.NETタイプから、ODP.NETでDbType
と OracleDbType
の両方のプロパティを推測します。ODP.NETを使用すると、アプリケーションでは、出力パラメータを.NET FrameworkタイプまたはODP.NETタイプのいずれかとして取得できます。アプリケーションでは、出力パラメータのDbType
プロパティ(.NETタイプ)、またはOracleParameter
オブジェクトのOracleDbType
プロパティ(ODP.NETタイプ)を設定することで、出力パラメータに対してどちらのタイプを戻すかを指定できます。たとえば、DbType
プロパティを設定することで出力パラメータがDbType.String
型として設定されている場合、出力データは.NET String型として戻されます。一方、OracleDbType
プロパティを設定することでパラメータがOracleDbType.Char
として設定されている場合、出力データはOracleString
型として戻されます。DbType
とOracleDbType
の両方のプロパティを設定してからコマンドを実行した場合は、最後の設定が有効になります。
ODP.NETは、次のOracleCommand
メソッドの実行により、OracleデータをInputOutput
、Output
およびReturnValue
パラメータに移入します。
-
ExecuteReader
-
ExecuteNonQuery
-
ExecuteScalar
アプリケーションは、出力パラメータの値をバインドできません。出力パラメータ値のバインドはODP.NETによって行われます。値オブジェクトが作成され、オブジェクトがOracleParameter
Value
プロパティに移入されます。
ファンクションに対して位置別(デフォルト)でバインドする場合、最初に他のパラメータより前にバインドされる戻り値がODP.NETに必要です。
この項の内容は次のとおりです。
関連項目:
3.8.3.1 コマンド・タイムアウト
コマンドをどのくらい実行すると例外で終了するか、その時間の長さはOracleCommand
CommandTimeout
プロパティによって制限されます。これを設定すると、長時間のコマンド実行でリソースが過剰に消費されたり、必要な他の操作が妨げられたりすることを避けられます。
データベース・サーバーは、アウト・オブ・バンド(OOB)で呼び出された場合はTCP/IP緊急データを介して、またイン・バンド・データで呼び出された場合はTCP/IP通常データを介して、それぞれ中断されることがあります。Windowsベースのデータベース・サーバーはイン・バンド中断しかサポートせず、他の(主としてUNIXベース)のデータベース・サーバーはOOBとイン・バンドどちらの中断もサポートします。
ODP.NET管理対象ドライバはデフォルトでOOB中断を使用し、データベース・サーバーがそれをサポートします。一部のネットワーク・トポロジの場合、データベースまでのルートに関係するルーターまたはファイアウォールが、緊急データまたはイン・バンド・データを削除するように構成されていた可能性があります。緊急データを適切に処理するようにルーターまたはファイアウォールを変更できない場合は、.NET構成パラメータDisable_Oob
をon
に設定すれば、イン・バンド中断を使用するようにODP.NET管理対象ドライバを構成できます。
関連項目:
詳細は、「Oracle Data Provider for .NET管理対象ドライバ」の項で、「settingsセクション」を参照してください。
3.8.3.2 OracleDbTypeの列挙型
OracleDbType
の列挙値は、OracleParameter
オブジェクトのOracleDbType
を明示的に指定する際に使用されます。
表3-7では、すべてのOracleDbType
の列挙値と、それぞれの列挙値の説明をリストしています。
表3-7 OracleDbTypeの列挙値
メンバー名 | 説明 |
---|---|
|
Oracleコレクション( ODP.NET管理対象ドライバでは使用できません |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
|
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
8バイトの |
|
2バイトの |
|
4バイトの |
|
8バイトの |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle Object型 ODP.NET管理対象ドライバでは使用できません |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle ODP.NET管理対象ドライバでは使用できません |
|
Oracle |
|
4バイトの |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
|
Oracle |
注意:
PL/SQLのLONG、LONG RAW、RAW
およびVARCHAR
データ型は、32512バイトまでのサイズにバインドできます。
3.8.3.3 DbType、OracleDbTypeおよび.NETタイプの判断
この項では、OracleParameter
クラス内のSystem.Data.DbType
、OracleDbType
およびValue
のプロパティからの判断を説明します。
OracleParameter
クラスでは、DbType
、OracleDbType
およびValue
プロパティはリンクされています。これらのプロパティのいずれかに値を指定すると、残りの1つ以上のプロパティの値を推測できます。
3.8.3.3.1 OracleDbTypeからのDbTypeの判断
OracleParameter
クラスでは、OracleDbType
の値を指定すると、表3-8に示されているとおりDbType
の値が判断されます。
表3-8 OracleDbTypeからのSystem.Data.DbTypeの判断
OracleDbType | System.Data.DbType |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3.8.3.3.2 DbTypeからのOracleDbTypeの判断
OracleParameter
クラスでは、DbType
の値を指定すると、表3-9に示されているとおりOracleDbType
の値が判断されます。
表3-9 DbTypeからのOracleDbTypeの判断
System.Data.DbType | OracleDbType |
---|---|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
サポート対象外 |
|
サポート対象外 |
|
サポート対象外 |
3.8.3.3.3 ValueからのDbTypeおよびOracleDbTypeの判断
OracleParameter
クラスでは、Value
は任意のNET Frameworkデータ型またはODP.NETタイプになるオブジェクト型です。OracleParameter
クラスにOracleDbType
プロパティおよびDbType
プロパティが指定されていない場合、OracleDbType
プロパティはValue
プロパティのタイプから推測されます。
表3-10は、Value
の型が.NET Frameworkデータ型の1つの場合における、Value
プロパティからのDbType
プロパティおよびOracleDbType
プロパティの判断を示します。
表3-10 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの判断
Value(.NETデータ型) | System.Data.DbType | OracleDbType |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object |
|
注意:
DbType
またはOracleDbType
プロパティを指定せずに、OracleParameter
クラスの値としてその他の.NET Frameworkデータ型を使用すると、例外が発生します。これは、その他の.NET Frameworkデータ型からのDbType
プロパティおよびOracleDbType
プロパティの判断がサポートされていないためです。
表3-11は、Value
の型がOracle.DataAccess.Types
の1つの場合における、Value
プロパティからのDbType
プロパティおよびOracleDbType
プロパティの判断を示しています。
表3-11 Value(ODP.NETタイプ)からのDbTypeおよびOracleDbTypeの判断
Value(Oracle.DataAccess.Types) | System.Data.DbType | OracleDbType |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3.8.3.4 PL/SQL連想配列バインド
ODP.NETは、PL/SQL連想配列(従来のPL/SQL索引付き表)バインドをサポートしています。
アプリケーションは、OracleParameter
オブジェクトをPL/SQL連想配列としてPL/SQLストアド・プロシージャにバインドできます。次のOracleParameter
プロパティは、この機能に使用されます。
-
このプロパティは、PL/SQL連想配列にバインドするために、
OracleCollectionType.PLSQLAssociativeArray
に設定する必要があります。 -
このプロパティは、固定長の要素タイプ(
Int32
など)の場合は無視されます。可変長の要素タイプ(
Varchar2
など)の場合、ArrayBindSize
プロパティ内の各要素は、Value
プロパティ内の対応する要素のサイズを指定します。Output
パラメータ、InputOutput
パラメータおよび戻り値の場合、このプロパティは、可変長の変数に対して指定する必要があります。データベース・サーバーが最大
32 KB VARCHAR2
をサポートする場合、各ODP.NET配列要素には最大32 KB
の文字またはバイナリ・データを格納できます。データベース・サーバーが最大4 KB VARCHAR2
をサポートする場合、各ODP.NET配列要素には最大4 KB
の文字または2 KB
のバイナリ・データを格納できます。 -
このプロパティは、
OracleParameter.Value
プロパティ内の各要素の実行ステータスを指定します。 -
このプロパティは、PL/SQL連想配列にバインドされる要素の最大数を指定します。
-
このプロパティは、値の配列に
NULL
またはDBNull.Value
を設定する必要があります。
ODP.NETはPL/SQL連想配列のバインド・パラメータをサポートしており、PL/SQL連想配列には次のデータ型があります。
-
BINARY_FLOAT
-
CHAR
-
DATE
-
NCHAR
-
NUMBER
-
NVARCHAR2
-
RAW
-
ROWID
-
UROWID
-
VARCHAR2
連想配列でサポートされていないデータ型を使用するとORA-600エラーが発生する場合があります。
PL/SQL連想配列の例
この例では、3つのOracleParameter
オブジェクトをPL/SQL連想配列としてバインドします。Param1
はIn
パラメータ、Param2
はInputOutput
パラメータ、Param3
はOutput
パラメータとしてバインドします。
PL/SQLパッケージ:MYPACK
/* Setup the tables and required PL/SQL: connect scott/tiger@oracle CREATE TABLE T1(COL1 number, COL2 varchar2(20)); CREATE or replace 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; / CREATE or REPLACE 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 Param2 to Param1\n Param3(1) := Param2(1); Param3(2) := NULL; Param3(3) := Param2(3); -- copy all elements from Param1 to Param2\n Param2(1) := Param1(1); Param2(2) := Param1(2); Param2(3) := Param1(3); -- insert some values to db\n FOR i IN 1..3 LOOP insert into T1 values(i,Param2(i)); END LOOP; END TestVarchar2; END MYPACK; / */ // C# using System; using System.Data; using Oracle.DataAccess.Client; class AssociativeArraySample { static void Main() { OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle"; con.Open(); Console.WriteLine("Connected to Oracle" + con.ServerVersion); OracleCommand cmd = new OracleCommand( "begin MyPack.TestVarchar2(:1, :2, :3); end;", con); OracleParameter Param1 = cmd.Parameters.Add("1", OracleDbType.Varchar2); OracleParameter Param2 = cmd.Parameters.Add("2", OracleDbType.Varchar2); OracleParameter Param3 = cmd.Parameters.Add("3", OracleDbType.Varchar2); 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 Console.WriteLine("parameter values after executing the PL/SQL block"); for (int i = 0; i < 3; i++) Console.WriteLine("Param2[{0}] = {1} ", i, (cmd.Parameters[1].Value as Array).GetValue(i)); for (int i = 0; i < 3; i++) Console.WriteLine("Param3[{0}] = {1} ", i, (cmd.Parameters[2].Value as Array).GetValue(i)); // Close and Dispose OracleConnection object con.Close(); con.Dispose(); Console.WriteLine("Disconnected"); } }
3.8.3.5 配列バインド
配列バインド機能を使用すると、アプリケーションでは、OracleParameter
クラスを使用してタイプの配列をバインドできます。配列バインド機能を使用すると、アプリケーションは、1回のデータベース・ラウンドトリップで複数の行を表に挿入できます。
次のコード例は、1回のデータベース・ラウンドトリップで3行をDept
表に挿入します。OracleCommand
ArrayBindCount
プロパティは、文の実行時に使用する配列の要素の数を定義します。
// C# using System; using System.Data; using Oracle.DataAccess.Client; class ArrayBindSample { static void Main() { OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;"; con.Open(); Console.WriteLine("Connected successfully"); int[] myArrayDeptNo = new int[3] { 10, 20, 30 }; OracleCommand cmd = new OracleCommand(); // Set the command text on an OracleCommand object cmd.CommandText = "insert into dept(deptno) values (:deptno)"; cmd.Connection = con; // 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(); Console.WriteLine("Insert Completed Successfully"); // Close and Dispose OracleConnection object con.Close(); con.Dispose(); } }
関連項目:
詳細は、Valueを参照してください
3.8.3.5.1 OracleParameterの配列バインド・プロパティ
OracleParameter
クラスは、配列バインド機能を使用するときに、詳細な制御を行うために2つのプロパティを提供します。
-
ArrayBindSize
プロパティは、配列内の対応する各値の最大サイズを指定する整数の配列です。ArrayBindSize
プロパティは、OracleParameter
オブジェクトのSize
プロパティに類似していますが、ArrayBindSize
プロパティは配列内の各値のサイズを指定するという点が異なります。アプリケーションは、実行前に
ArrayBindSize
プロパティを移入する必要があります。ODP.NETは、実行後にArrayBindSizeプロパティを移入します。ArrayBindSize
プロパティは、Clob
、Blob
、Varchar2
など、可変長のパラメータ・タイプにのみ使用されます。Unicode文字列タイプのバイナリ・データ型および文字の場合、サイズはバイトで表されます。文字列タイプのカウントには、終了文字は含まれません。サイズが明示的に設定されていない場合は、値の実際のサイズから推測されます。出力パラメータの場合、各値のサイズはODP.NETにより設定されます。固定長のデータ型の場合、ArrayBindSize
プロパティは無視されます。文字でもバイナリ・データでも、最大
ArrayBindSize
サイズは2GB
です。 -
ArrayBindStatus
プロパティは、パラメータの配列内の対応する各値のステータスを指定するOracleParameterStatus
値の配列です。このプロパティは、OracleParameter
のStatus
プロパティに類似していますが、ArrayBindStatus
プロパティは配列内の各値のステータスを指定するという点が異なります。アプリケーションは、実行前に
ArrayBindStatus
プロパティを移入する必要があります。ODP.NETは、実行後に移入します。ArrayBindStatus
プロパティを使用するアプリケーションは、実行前に、パラメータの配列内の対応する要素にNULL
値を指定できます。ODP.NETは、実行後にArrayBindStatus
プロパティを移入して、配列内の対応する要素にNULL
値があるか、または値がフェッチされたときにデータの切捨てが発生したかどうかを示します。
3.8.3.5.2 配列バインドのエラー処理
配列バインドの実行中にエラーが発生した場合、Value
プロパティ内のどの要素がエラーの原因になったかを判断するのは困難です。ODP.NETは、エラーが発生した行を判断する方法を提供することで、エラーの原因になった行の要素を簡単に検索できるようにします。
配列バインドの実行中にOracleException
オブジェクトがスローされた場合、OracleErrorCollection
には1つ以上のOracleError
オブジェクトが含まれます。これらのOracleError
オブジェクトはそれぞれ、実行中に発生した個別のエラーを表し、プロバイダ固有のプロパティArrayBindIndex
を含みます。
次に配列バインドのエラー処理の例を示します。
/* Database Setup connect scott/tiger@oracle drop table depttest; create table depttest(deptno number(2)); */ // C# using System; using System.Data; using Oracle.DataAccess.Client; class ArrayBindExceptionSample { static void Main() { OracleConnection con = new OracleConnection(); con.ConnectionString = "User Id=scott;Password=tiger;Data Source=oracle;"; con.Open(); OracleCommand cmd = new OracleCommand(); // Start a transaction OracleTransaction txn = con.BeginTransaction(IsolationLevel.ReadCommitted); try { int[] myArrayDeptNo = new int[3] { 10, 200000, 30 }; // int[] myArrayDeptNo = new int[3]{ 10,20,30}; // Set the command text on an OracleCommand object cmd.CommandText = "insert into depttest(deptno) values (:deptno)"; cmd.Connection = con; // 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(); } catch (OracleException e) { Console.WriteLine("OracleException {0} occured", e.Message); if (e.Number == 24381) 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); txn.Commit(); } cmd.Parameters.Clear(); cmd.CommandText = "select count(*) from depttest"; decimal rows = (decimal)cmd.ExecuteScalar(); Console.WriteLine("{0} row have been inserted", rows); con.Close(); con.Dispose(); } }
関連項目:
詳細は、ArrayBindIndexを参照してください。
3.8.3.5.3 OracleParameterStatusの列挙型
表3-12に、OracleParameterStatus
の列挙値をリストします。
表3-12 OracleParameterStatusのメンバー
メンバー名 | 説明 |
---|---|
|
入力パラメータの場合、入力値が列に割り当てられたことを示します。 出力パラメータの場合、プロバイダによってそのままの値がパラメータに割り当てられたことを示します。 |
|
|
|
|
|
列からデータをフェッチする際に切捨てが行われたことを示します。 |
3.8.4 バッチ処理
OracleDataAdapter.Update
メソッドがコールされると、OracleDataAdapter
UpdateBatchSize
プロパティではバッチ処理が有効になります。UpdateBatchSize
は、各ラウンドトリップで、Oracle Databaseを更新するDataSet行数を示す数値プロパティです。
これにより、開発者はデータベースへのラウンド・トリップの回数を削減できます。
関連項目:
3.8.5 文キャッシング
文キャッシングにより、最初の実行で作成されたサーバー・カーソルのキャッシングによる実行の前に、各SQL文またはPL/SQL文を解析する必要がなくなります。同じ文を後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスが向上します。
文キャッシングによるパフォーマンスの向上を得るために、繰り返し実行される文のみをキャッシュすることをお薦めします。さらに、SQL文またはPL/SQL文では、リテラル値ではなくパラメータを使用してください。これにより、文キャッシングが有効になります。これは、後続の実行でパラメータ値が異なる場合でも、パラメータ化された文から解析された情報は再利用できるためです。ただし、文のリテラル値が異なる場合、解析された情報は、後続の文にも同じリテラル値がないかぎり、再使用できません。
3.8.5.1 文キャッシングの接続文字列属性
次の接続文字列属性は、ODP.NET文キャッシング機能の動作を制御します。
-
Statement
Cache
Size
この属性は、ODP.NET文キャッシングを有効化または無効化します。デフォルトでは、この属性は
0
(無効)に設定されます。0
より大きい値に設定すると、ODP.NET文キャッシングが有効になり、指定された値は接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。自動チューニングを有効にすると、文キャッシングも有効になります。その場合、
Statement Cache Size
は自動的に構成されます。 -
Statement
Cache
Purge
この属性は、接続がクローズされた場合、または接続プールに戻された場合にキャッシュされるすべての文を消去する方法を提供します。デフォルトでは、この属性は
false
に設定されています。つまり、接続がプールに戻されてもカーソルは解放されません。
3.8.5.2 レジストリを使用した文キャッシングの有効化
アプリケーションを変更せずに、システムで実行しているすべてのODP.NETアプリケーションの文キャッシングをデフォルトで有効化するには、HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET\
Assembly_Version
\StatementCacheSize
のレジストリ・キーを0
より大きい値に設定します。この値は、サーバーでキャッシュされるカーソルの数を指定します。
システムのデフォルト値は、接続プール・レベルで無視できます。Statement
Cache
Size
属性は、レジストリ値とは異なるサイズに設定するか、無効にできます。Statement
Cache
Size
は、XML構成ファイルで設定することもできます。
関連項目:
詳細は、「Oracle Data Provider for .NETの構成」を参照してください。3.8.5.3 文キャッシングのメソッドおよびプロパティ
次のプロパティおよびメソッドは、文キャッシングが有効な場合のみ当てはまります。
-
OracleCommand.AddToStatementCache
プロパティ文キャッシングが有効な場合、このプロパティを
true
に設定すると、文の実行時にキャッシュに文が追加されます。デフォルトでは、このプロパティはtrueに設定されています。文キャッシングが無効な場合、またはこのプロパティがfalse
に設定されている場合、実行された文はキャッシュされません。 -
OracleConnection.PurgeStatementCache
メソッドこのメソッドは、特定の接続に関連付けられたデータベースでオープンしているカーソルをすべてクローズすることで、キャッシュされた文をすべて消去します。このコールの後も、文キャッシングは有効です。
3.8.5.4 接続と文キャッシング
文キャッシングは、接続ごとに個別に管理されます。このため、異なる接続で同じ文を実行するには、接続ごとに1回消去して、接続ごとに個別のカーソルをキャッシュする必要があります。
3.8.5.5 プーリングと文キャッシング
プーリングと文キャッシングは同時に使用できます。接続プーリングが有効で、Statement
Cache
Purge
属性がfalse
に設定されている場合、個別の接続で実行される文は、プールされた接続の存続期間を通じてキャッシュされます。
Statement
Cache
Purge
属性がtrue
に設定されている場合は、接続がプールに戻されたときに、キャッシュされたすべてのカーソルが解放されます。接続プーリングが無効な場合、カーソルは接続の存続中にキャッシュされますが、OracleConnection
オブジェクトがクローズまたは処理されたときにはクローズされます。
3.8.6 自動チューニング
ODP.NETアプリケーションの自動チューニングを行ってパフォーマンスを最適化することができます。ODP.NETは実行時のアプリケーション問合せを動的に監視します。
注意:
Pooling
接続文字列属性がfalse
に設定されている場合、アプリケーションの自動チューニングは実行されません。また、自動チューニングは.NETストアド・プロシージャではサポートされません。
文キャッシュ・サイズ(StatementCacheSize)は、アプリケーションによって実行される文を監視することで自動的にチューニングされます。次の各項では、アプリケーションの自動チューニングについて説明します。
3.8.6.1 文キャッシングの自動チューニング
文キャッシングを使用すると、各SQL文またはPL/SQL文を実行前に再解析する必要がなくなり、パフォーマンスが向上します。
アプリケーションの自動チューニングが有効な場合、ODP.NETは文キャッシュ・サイズの最適な値を決定するためにアプリケーションの動作を継続的に監視します。接続文字列、構成ファイルまたはレジストリに指定した文キャッシュ・サイズの値は無視されます。
アプリケーションが最初に初期化されるときは、文キャッシュ・サイズのデフォルト値が使用されます。アプリケーションが文を実行するのと並行して、ODP.NETは文キャッシュ・サイズの値の自動チューニングに使用される統計を収集します。文キャッシュ・サイズの自動チューニングを行うとパフォーマンスが向上します。
注意:
文キャッシングの利点を最大限活用するには、文の実行ごとに異なるインライン値で文を動的に生成しないでください。かわりに、パラメータ化されたコマンドを使用して、実行およびキャッシュする必要がある一意の文の数を最小限にします。これは、パラメータ値や文の実行回数にかかわらず、一意の各コマンド・テキストでキャッシュする必要のある文が1つのみになるためです。
接続ごとにキャッシュできる文の最大数は、MaxStatementCacheSize
構成属性によって決まります。MaxStatementCacheSize
の値は、WindowsレジストリまたはXML構成ファイルで指定できます。
MaxStatementCacheSize
設定は、キャッシュされる文の数やオープンしているカーソル数を制限する場合に便利です。これは、キャッシュされる文は、サーバーでオープンになっているカーソルと等しいためです。このため、MaxStatementCacheSize
をデータベースのOPEN_CURSORS
設定よりも大きい値に設定しないでください。
MaxStatementCacheSize
構成属性を構成するには、次のWindowsレジストリ・キーを使用します。
HKLM\Software\Oracle\ODP.NET\version\MaxStatementCacheSize
MaxStatementCacheSize
キーの種類はREG_SZ
です。これは、0からSystem.Int32.MaxValue
の整数値に設定できます。
次の例では、ADO.NET 2.0以上の構成ファイルでMaxStatementCacheSize
プロパティを設定しています。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <oracle.dataaccess.client> <settings> <add name="MaxStatementCacheSize" value="300"/> </settings> </oracle.dataaccess.client> </configuration>
アプリケーションの自動チューニングが無効な場合、文キャッシュ・サイズの値は接続文字列、構成ファイルまたはレジストリの設定によって決まります。これらのソースのいずれにも文キャッシュ・サイズが指定されていない場合、文キャッシュ・サイズのデフォルト値は0に設定されます。旧リリースのODP.NETと同じデフォルト設定でODP.NETを構成するには、自動チューニングを無効化し、StatementCacheSize
値を10に設定します。
関連項目:
3.8.6.2 アプリケーションの自動チューニングの有効化または無効化
ODP.NETアプリケーションの自動チューニングはデフォルトで有効になっています。アプリケーションの自動チューニングを有効化または無効化するには、次のいずれかの方法を使用します。
-
自動チューニングの接続文字列属性
Self Tuning
接続文字列属性を変更すると、特定の接続プールについてアプリケーションの自動チューニングを有効化または無効化できます。Self Tuning
のデフォルト値はtrue
です。 -
Windowsレジストリ
次のレジストリ・エントリを変更すると、ODP.NETの特定のバージョンについてアプリケーションの自動チューニングを有効化または無効化できます。
HKLM\Software\Oracle\ODP.NET\version\SelfTuning
SelfTuning
キーの種類はREG_SZ
です。1
(有効)または0
(無効)に設定できます。 -
構成ファイル
アプリケーション構成ファイル(
app.config
)またはWeb構成ファイル(web.config
)を変更すると、ODP.NETアプリケーションの自動チューニングを有効化または無効化できます。次の例は、ADO.NET 2.0.xのアプリケーション構成ファイルで自動チューニングを有効化する方法を示しています。
<?xml version="1.0" encoding="utf-8" ?> <configuration> <oracle.dataaccess.client> <settings> <add name="SelfTuning" value="1"/> </settings> </oracle.dataaccess.client> </configuration>
注意:
アプリケーションの最適な文キャッシュ・サイズがわかっている場合、自動チューニングを無効化して、レジストリ、構成ファイルまたはアプリケーションで
StatementCacheSize
を最適な値に設定できます。自動チューニングが無効化されていて、StatementCacheSize
がまったく設定されていない場合、StatementCacheSize
にはデフォルト値の0が使用されます。
3.8.6.3 最適化のための変更のトレース
自動チューニングによる最適化のための変更をアプリケーションでトレースできます。StatementCacheSize
に加えられたすべての変更がトレースされます。エラーがあれば、それもトレースされます。
自動チューニングのトレースに使用されるTraceLevel
は64
です。
関連項目:
TraceLevel
値の詳細は、表2-2を参照