OracleCommandオブジェクトは、Oracle Databaseで実行されるSQL文またはストアド・プロシージャを表します。
この項の内容は次のとおりです。
Oracle Databaseは、接続のコンテキストでのみトランザクションを開始します。トランザクションが開始すると、その接続で引き続き行われるコマンド実行はすべて、そのトランザクションのコンテキストで実行されます。トランザクションはOracleConnectionオブジェクトでのみ開始され、OracleConnectionオブジェクトのTransaction読取り専用プロパティは、OracleConnectionオブジェクトによって暗黙的に設定されます。このため、アプリケーションはTransactionプロパティを設定できません。また、設定する必要もありません。
|
注意: トランザクションは、.NETストアド・プロシージャではサポートされません。 |
OracleParameterオブジェクトのDbTypeプロパティが設定されている場合、OracleParameterオブジェクトのOracleDbTypeプロパティも変更されます。その逆も同じです。パラメータ・セットは最後に有効になります。アプリケーションはデータをバインドして、パラメータ値の.NETタイプから、ODP.NETでDbTypeとOracleDbTypeの両方のプロパティを推測します。ODP.NETを使用すると、アプリケーションでは、出力パラメータを.NETフレームワーク・タイプまたは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では、他のパラメータより前に戻り値がまずバインドされることが想定されています。
この項の内容は次のとおりです。
Oracle Database 10g以上のデータベースでは、BINARY_FLOATおよびBINARY_DOUBLEという2つの新しいネイティブ・データ型がサポートされています。
BINARY_FLOATおよびBINARY_DOUBLEデータ型はそれぞれ、単精度浮動小数点値と倍精度小数点値を表します。
OracleParameterバインドでは、アプリケーションは、BINARY_FLOATおよびBINARY_DOUBLEデータ型には、OracleDbType.BinaryFloatおよびOracleDbType.BinaryDoubleの列挙を使用する必要があります。
OracleDbTypeの列挙値は、OracleParameterオブジェクトのOracleDbTypeを明示的に指定する際に使用されます。
表3-3に、OracleDbTypeの列挙値と、それぞれの列挙値の説明を示します。
表3-3 OracleDbType列挙値
| メンバー名 | 説明 |
|---|---|
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
|
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
8バイトの |
|
|
2バイトの |
|
|
4バイトの |
|
|
8バイトの |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracleオブジェクト型 |
|
|
Oracle |
|
|
Oracle |
|
|
Oracleネスト表型 |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
4バイトの |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
この項では、OracleParameterクラス内のSystem.Data.DbType、OracleDbTypeおよびValueのプロパティからの判断を説明します。
OracleParameterクラスでは、DbType、OracleDbTypeおよびValueプロパティはリンクされています。これらのプロパティのいずれかに値を指定すると、残りの1つ以上のプロパティの値を推測できます。
OracleParameterクラスでは、OracleDbTypeの値を指定すると、表3-4に示すように、DbTypeの値が判断されます。
表3-4 OracleDbTypeからのSystem.Data.DbTypeの判断
| OracleDbType | System.Data.DbType |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OracleParameterクラスでは、DbTypeの値を指定すると、表3-5に示すように、OracleDbTypeの値が判断されます。
表3-5 DbTypeからのOracleDbTypeの判断
| System.Data.DbType | OracleDbType |
|---|---|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
サポート対象外 |
|
|
サポート対象外 |
|
|
サポート対象外 |
OracleParameterクラスでは、Valueは任意のNET Frameworkデータ型またはODP.NETタイプになるオブジェクト・タイプです。OracleParameterクラスにOracleDbTypeプロパティおよびDbTypeプロパティが指定されていない場合、OracleDbTypeプロパティはValueプロパティのタイプから推測されます。
表3-6は、Valueのタイプが.NETフレームワーク・データ型の1つである場合の、ValueプロパティからのDbTypeおよびOracleDbTypeプロパティの判断を示します。
表3-6 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの判断
| Value(.NETデータ型) | System.Data.DbType | OracleDbType |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
注意: DbTypeまたはOracleDbTypeを指定せずに、OracleParameterの値としてその他の.NETフレームワーク・データ型を使用すると、例外が発生します。これは、その他の.NETフレームワーク・データ型からのDbTypeプロパティおよびOracleDbTypeプロパティの判断がサポートされていないためです。 |
表3-7は、ValueのタイプがOracle.DataAccess.Types型の1つである場合の、Valueプロパティから判断されたDbTypeおよびOracleDbTypeプロパティを示します。
表3-7 Value(ODP.NETデータ型)からのDbTypeおよびOracleDbTypeの判断
| Value(Oracle.DataAccess.Types) | System.Data.DbType | OracleDbType |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ODP.NETは、PL/SQL連想配列(従来のPL/SQL索引付き表)バインドをサポートしています。
アプリケーションは、OracleParameterオブジェクトをPL/SQL連想配列としてPL/SQLストアド・プロシージャにバインドできます。次のOracleParameterプロパティは、この機能に使用されます。
このプロパティは、PL/SQL連想配列にバインドするために、OracleCollectionType.PLSQLAssociativeArrayに設定する必要があります。
このプロパティは、固定長の要素タイプ(Int32など)の場合は無視されます。
可変長の要素タイプ(Varchar2など)の場合、ArrayBindSizeプロパティ内の各要素は、Valueプロパティ内の対応する要素のサイズを指定します。
Outputパラメータ、InputOutputパラメータおよび戻り値の場合、このプロパティは、可変長の変数に対して指定する必要があります。
このプロパティは、OracleParameter.Valueプロパティ内の各要素の実行ステータスを指定します。
このプロパティは、PL/SQL連想配列にバインドされる要素の最大数を指定します。
このプロパティは、値の配列にNULLまたはDBNull.Valueを設定する必要があります。
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");
}
}
配列バインド機能を使用すると、アプリケーションでは、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();
}
}
OracleParameterクラスは、配列バインド機能を使用するときに、詳細な制御を行うために2つのプロパティを提供します。
ArrayBindSizeプロパティは、配列内の対応する各値の最大サイズを指定する整数の配列です。ArrayBindSizeプロパティは、OracleParameterのSizeプロパティに類似していますが、ArrayBindSizeプロパティは配列内の各値のサイズを指定するという点が異なります。
アプリケーションは、実行前にArrayBindSizeプロパティを移入する必要があります。ODP.NETは、実行後にArrayBindSizeプロパティを移入します。
ArrayBindSizeプロパティは、Clob、Blob、Varchar2など、可変長のパラメータ・タイプにのみ使用されます。Unicode文字列タイプのバイナリ・データ型および文字の場合、サイズはバイトで表されます。文字列タイプのカウントには、終了文字は含まれません。サイズが明示的に設定されていない場合、値の実際のサイズから推測されます。出力パラメータの場合、それぞれの値のサイズはODP.NETにより設定されます。固定長のデータ型の場合、ArrayBindSizeプロパティは無視されます。
ArrayBindStatusプロパティは、パラメータの配列内の対応する各値のステータスを指定するOracleParameterStatus値の配列です。このプロパティは、OracleParameterのStatusプロパティに類似していますが、ArrayBindStatusプロパティは配列内の各値のステータスを指定するという点が異なります。
アプリケーションは、実行前にArrayBindStatusプロパティを移入する必要があります。ODP.NETは、実行後に移入します。ArrayBindStatusプロパティを使用するアプリケーションは、実行前に、パラメータの配列内の対応する要素にNULL値を指定できます。ODP.NETは、実行後にArrayBindStatusプロパティを移入して、配列内の対応する要素にNULL値があるか、または値がフェッチされたときにデータの切捨てが発生したかどうかを示します。
配列バインドの実行中にエラーが発生した場合、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();
}
}
表3-8は、OracleParameterStatusの列挙値のリストです。
文キャッシングにより、最初の実行で作成されたサーバー・カーソルのキャッシングによる実行の前に、各SQL文またはPL/SQL文を解析する必要がなくなります。同じ文を後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスが向上します。
文キャッシングによるパフォーマンスの向上を得るために、繰り返し実行される文のみをキャッシュすることをお薦めします。さらに、SQL文またはPL/SQL文では、リテラル値ではなくパラメータを使用してください。これにより、文キャッシングが有効になります。これは、後続の実行でパラメータ値が異なる場合でも、パラメータ化された文から解析された情報は再利用できるためです。ただし、文のリテラル値が異なる場合、解析された情報は、後続の文にも同じリテラル値がないかぎり、再使用できません。
次の接続文字列属性は、ODP.NET文キャッシング機能の動作を制御します。
Statement Cache Size
この属性は、ODP.NET文キャッシングを有効化または無効化します。デフォルトでは、この属性は10に設定され、ODP.NET文キャッシングは有効です。0に設定した場合、属性は無効になります。0より大きい値に設定した場合、ODP.NET文キャッシングが有効になり、指定された値は、接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。
Statement Cache Purge
この属性は、接続がクローズされた場合、または接続プールに戻された場合にキャッシュされるすべての文を消去する方法を提供します。デフォルトでは、この属性はfalseに設定されています。つまり、接続がプールに戻されてもカーソルは解放されません。
アプリケーションを変更せずに、システムで実行しているすべてのODP.NETアプリケーションの文キャッシングをデフォルトで有効化するには、HKEY_LOCAL_MACHINE\SOFTWARE\ORACLE\ODP.NET\Assembly_Version \StatementCacheSizeのレジストリ・キーを0より大きい値に設定しますこの値は、サーバーでキャッシュされるカーソルの数を指定します。デフォルトでは、この値は10に設定されています。
システムのデフォルト値は接続プール・レベルで無効にできます。Statement Cache Size属性をレジストリ値と異なるサイズに設定するか、またはこの属性をオフにできます。
次のプロパティおよびメソッドは、文キャッシングが有効な場合のみ当てはまります。
OracleCommand.AddToStatementCacheプロパティ
文キャッシングが有効な場合、このプロパティをtrueに設定すると、文の実行時にキャッシュに文が追加されます。文キャッシングが無効な場合、またはこのプロパティがfalseに設定されている場合、実行された文はキャッシュされません。
OracleConnection.PurgeStatementCacheメソッド
このメソッドは、特定の接続に関連付けられたデータベースでオープンしているカーソルをすべてクローズすることで、キャッシュされた文をすべて消去します。このコールの後も、文キャッシングは有効です。