OracleCommandオブジェクト
OracleCommandオブジェクトは、Oracle Databaseで実行されるSQL文またはストアド・プロシージャを表します。
ノート:
オプティマイザのヒント構文形式--+ ...はサポートされていません。ODP.NETでは、/*+ ... */の構文をサポートしています。
この項の内容は次のとおりです。
トランザクション
Oracle Databaseは、接続のコンテキストでのみトランザクションを開始します。トランザクションが開始すると、その接続で引き続き行われるコマンド実行はすべて、そのトランザクションのコンテキストで実行されます。トランザクションはOracleConnectionオブジェクトでのみ開始され、OracleCommandオブジェクトのTransaction読取り専用プロパティは、OracleConnectionオブジェクトによって暗黙的に設定されます。このため、アプリケーションはTransactionプロパティを設定できません。また、設定する必要もありません。
ノート:
トランザクションは、.NETストアド・プロシージャではサポートされません。
"FOR UPDATE"および"RETURNING"句を含むSQL文には明示的なトランザクションが必要です。グローバル・トランザクションが使用されていない場合は不要です。
System.TransactionsとPromotable Transaction
ODP.NETはSystem.Transactionsをサポートします。Oracle DatabaseへのSystem.Transactionsスコープでオープンされた最初の接続に対しては、ローカル・トランザクションが作成されます。2番目の接続がオープンされると、このトランザクションは自動的に分散トランザクションに昇格します。この機能は、パフォーマンスとスケーラビリティの向上を実現します。
TransactionScopeやServicedComponentなどのトランザクション・コンテキスト内で作成された接続は、様々なリリースのOracle Databaseに対して確立できます。ただし、ローカル・トランザクションを昇格できるようにするには、次の条件を満たす必要があります。
-
トランザクション・コンテキストの最初の接続は、Oracle Databaseに対して確立する必要があります。
-
ローカル・トランザクションの昇格にはOracle Services for Microsoft Transaction Serverが必要です。この要件を満たしていない場合、同じトランザクション・コンテキスト内にある2番目の接続要求で例外がスローされます。
データベースのトランザクションがすでに分散されているときにトランザクションを昇格すると、データベース・リンクの使用によりORA-24797エラーがスローされます。
アプリケーションがSystem.Transactionsを使用する場合は、enlist接続文字列属性をtrue(デフォルト)またはdynamicのいずれかに設定する必要があります。ただし、自動登録するにはenlist=trueである必要があるため、TransactionScopeとともにenlist=dynamicを使用することはできません。
ODP.NETは、分散トランザクションを使用するアプリケーション用に、次のSystem.Transactionsプログラミング・モデルをサポートしています。
ノート:
ODP.NET Coreは分散トランザクションをサポートしていません
TransactionScopeを使用した暗黙的なトランザクション登録
TransactionScopeクラスは、トランザクションに明示的に登録する必要のないトランザクション・アプリケーションを記述するためのメカニズムを提供します。これを実現するには、アプリケーションでTransactionScopeオブジェクトを使用して、トランザクション・コードを定義します。このトランザクション・スコープ内で作成された接続は、分散トランザクションへの昇格が可能なローカル・トランザクションに登録されます。
変更をコミットするには、アプリケーションで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);
}
}
}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);
}
}
}関連項目:
分散トランザクション
分散トランザクションは1つ以上の文からなり、それらが個別に、またはグループとして、分散データベースの複数ノードのデータを更新します。
ODP.NET管理対象ドライバと管理対象外ドライバは、Microsoft Distributed Transaction Coordinator (MSDTC)およびOracleデータベースと統合されます。MSDTCは、同じSystem.Transactionsオブジェクトに入っているあらゆるリソース・マネージャと連係し、2フェーズ・コミットまたはロールバックをアトミックに実行します。これにより、Oracle分散トランザクションは、ネットワーク全体で正常にコミットまたはロールバックすることができます。
ODP.NETでは、分散トランザクションにコミット読取り分離レベルのみがサポートされています。
ノート:
ODP.NET Coreは分散トランザクションをサポートしていません。
Microsoft Distributed Transaction Coordinatorの統合
管理対象ODP.NETには、分散トランザクション登録、コミットおよびロールバックのためにMSDTCとの統合をサポートする、ネイティブで完全な管理対象実装が含まれます。
管理対象外ODP.NETの場合、Oracle Services for Microsoft Transaction (OraMTS)がMSDTCとの統合を提供し、クライアント・コンポーネントがOracleデータベース分散トランザクションに参加できるようになります。OraMTSは、MSDTCに対するOracleデータベースのプロキシとして動作し、Oracle分散データベース・トランザクションを残りの分散トランザクションとともにコミットまたはロールバックできるようにします。
管理対象外ODP.NETは、管理対象または管理対象外のOraMTS実装を使用できます。Oracle RACまたはData Guardからの高可用性を必要とするアプリケーションでは、管理対象OraMTSの使用をお薦めします。
分散トランザクションでネットワーク障害やサーバー・ハードウェア障害などの障害が発生した場合、インプロセス・トランザクションをインダウトにしておくことができます。管理対象および管理対象外のODP.NETはどちらも、OraMTSリカバリ・サービスを使用して、これらのインダウト・トランザクションを解決します。このリカバリ・サービスはWindowsサービスとして実行します。管理者は、OraMTS Windowsリカバリ・サービスをインストールおよび構成して、管理対象と管理対象外のどちらのODP.NETを使用するかについてのリカバリ・シナリオを管理する必要があります。各マシンに必要なリカバリ・サービスは1つのみです。
OraMTS Recoveryサービスを、ODP.NETが稼働していてMSDTCに参加しているすべてのクライアント・マシンにインストールする必要があります。マシンには複数のIPアドレスがある可能性があるため、管理対象ODP.NETアプリケーションの管理者は、アプリケーションの.NET構成ファイルでリカバリ・サービスが稼働しているホスト・マシン名またはIPアドレスを指定できます。ODP.NET管理対象外ドライバは、リカバリ・サービスのIP/マシン名を自動的に解決します。
表3-7 分散トランザクションでサポートされるODP.NETのタイプと.NET Frameworkのバージョン
| ODP.NETタイプ | .NET Frameworkバージョン | 分散トランザクション・サポート |
|---|---|---|
|
管理対象 |
4.x |
分散トランザクションに対する.NET Frameworkのネイティブ管理対象実装。 |
|
管理対象外 |
4.x |
OraMTS (デフォルト)または管理対象OraMTS実装。Oracle RACまたはData Guardからの高可用性を必要とする管理対象外ODP.NETアプリケーションでは、管理対象OraMTSの使用をお薦めします。 |
|
管理対象外 |
3.5 |
OraMTS |
関連項目:
『Oracle Services for Microsoft Transaction Server開発者ガイド for Microsoft Windows』のOracle MTS Recovery Serviceの手動作成に関する項。
ODP.NET管理対象ドライバ設定
この項では、ODP.NET管理対象ドライバで分散トランザクションを使用するために必要な設定および構成ステップを説明します。これらの.NETフレームワーク・バージョンで分散トランザクションを構成するには、次のステップを実行します。
-
OraMTSリカバリ・サービスを作成して設定するか、既存のリカバリ・サービスが実行されていることを確認します。
-
OraMTSリカバリ・サービスが稼働しているポート番号を指定するには、.NET構成で
OMTSRECO_PORTの値を設定します。
ODP.NET管理対象外ドライバ設定
この項では、ODP.NET管理対象外ドライバとともに分散トランザクションを使用するために必要な設定および構成ステップを説明します。
.NET Framework 4.xの場合、ODP.NET管理対象外ドライバのアセンブリには管理対象OraMTSが含まれます。OraMTSは、アップグレード時に実装を継続できるよう、ODP.NET管理対象外ドライバのデフォルトのオプションです。ただし、Oracle Real Application ClustersまたはOracle Data Guardとともに高可用性FAN操作(HA Events = true)を使用する場合、管理対象OraMTSオプションを使用することをお薦めします。管理対象OraMTSオプションでは高可用性機能がサポートされますが、従来のOraMTSではサポートされません。
アプリケーションでは、.NET構成ファイルのUseOraMTSManagedパラメータを使用して、OraMTS (デフォルト)または管理対象OraMTSの使用を設定できます。
ODP.NET管理対象外ドライバに従来のOraMTS実装を使用するリカバリ・サービスを含めて、OraMTSをインストールして構成します。
管理対象OraMTSを設定するには、次のステップを実行します。
-
.NET構成ファイルで
UseOraMTSManagedをtrueに設定します。 -
OraMTSリカバリ・サービスを作成して設定するか、既存のリカバリ・サービスが実行されていることを確認します。
関連項目:
.NET構成の設定の詳細は、「distributedTransactionセクション」を参照してください
パラメータ・バインド
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に必要です。
この項の内容は次のとおりです。
関連項目:
コマンド・タイムアウト
コマンドをどのくらい実行すると例外で終了するか、その時間の長さは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セクション」を参照してください。
OracleDbTypeの列挙型
OracleDbTypeの列挙値は、OracleParameterオブジェクトのOracleDbTypeを明示的に指定する際に使用されます。
表3-8では、すべてのOracleDbTypeの列挙値と、それぞれの列挙値の説明をリストしています。
表3-8 OracleDbTypeの列挙値
| メンバー名 | 説明 |
|---|---|
|
|
Oracleコレクション( ODP.NET管理対象ドライバおよびODP.NET Coreでは使用できません |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
|
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
8バイトの |
|
|
2バイトの |
|
|
4バイトの |
|
|
8バイトの |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle Object型 ODP.NET管理対象ドライバおよびODP.NET Coreでは使用できません |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle ODP.NET管理対象ドライバおよびODP.NET Coreでは使用できません |
|
|
Oracle |
|
|
4バイトの |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
|
|
Oracle |
ノート:
PL/SQLのLONG、LONG RAW、RAWおよびVARCHARデータ型は、32512バイトまでのサイズにバインドできます。
DbType、OracleDbTypeおよび.NETタイプの判断
この項では、OracleParameterクラス内のSystem.Data.DbType、OracleDbTypeおよびValueのプロパティからの判断を説明します。
OracleParameterクラスでは、DbType、OracleDbTypeおよびValueプロパティはリンクされています。これらのプロパティのいずれかに値を指定すると、残りの1つ以上のプロパティの値を推測できます。
OracleDbTypeからのDbTypeの判断
OracleParameterクラスでは、OracleDbTypeの値を指定すると、表3-9に示されているとおりDbTypeの値が判断されます。
表3-9 OracleDbTypeからのSystem.Data.DbTypeの判断
| OracleDbType | System.Data.DbType |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DbTypeからのOracleDbTypeの判断
OracleParameterクラスでは、DbTypeの値を指定すると、表3-10に示されているとおりOracleDbTypeの値が判断されます。
表3-10 DbTypeからのOracleDbTypeの判断
| System.Data.DbType | OracleDbType |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
サポート対象外 |
|
|
サポート対象外 |
|
|
サポート対象外 |
|
|
サポート対象外 |
ValueからのDbTypeおよびOracleDbTypeの判断
OracleParameterクラスでは、Valueは任意のNET Frameworkデータ型またはODP.NETタイプになるオブジェクト型です。OracleParameterクラスにOracleDbTypeプロパティおよびDbTypeプロパティが指定されていない場合、OracleDbTypeプロパティはValueプロパティのタイプから推測されます。
表3-11は、Valueの型が.NET Frameworkデータ型の1つの場合における、ValueプロパティからのDbTypeプロパティおよびOracleDbTypeプロパティの判断を示します。
表3-11 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの判断
| Value(.NETデータ型) | System.Data.DbType | OracleDbType |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Object |
|
ノート:
DbTypeまたはOracleDbTypeプロパティを指定せずに、OracleParameterクラスの値としてその他の.NET Frameworkデータ型を使用すると、例外が発生します。これは、その他の.NET Frameworkデータ型からのDbTypeプロパティおよびOracleDbTypeプロパティの判断がサポートされていないためです。
表3-12は、Valueの型がOracle.DataAccess.Typesの1つの場合における、ValueプロパティからのDbTypeプロパティおよびOracleDbTypeプロパティの判断を示しています。
表3-12 Value(ODP.NETタイプ)からのDbTypeおよびOracleDbTypeの判断
| Value(Oracle.DataAccess.Types) | System.Data.DbType | OracleDbType |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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");
}
}
配列バインド
配列バインド機能を使用すると、アプリケーションでは、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を参照してください
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値があるか、または値がフェッチされたときにデータの切捨てが発生したかどうかを示します。
配列バインドのエラー処理
配列バインドの実行中にエラーが発生した場合、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を参照してください。
OracleParameterStatusの列挙型
表3-13に、OracleParameterStatusの列挙値をリストします。
表3-13 OracleParameterStatusメンバー
| メンバー名 | 説明 |
|---|---|
|
|
入力パラメータの場合、入力値が列に割り当てられたことを示します。 出力パラメータの場合、プロバイダによってそのままの値がパラメータに割り当てられたことを示します。 |
|
|
|
|
|
|
|
|
列からデータをフェッチする際に切捨てが行われたことを示します。 |
バッチ処理
OracleDataAdapter.Updateメソッドがコールされると、OracleDataAdapter UpdateBatchSizeプロパティではバッチ処理が有効になります。UpdateBatchSizeは、各ラウンドトリップで、Oracle Databaseを更新するDataSet行数を示す数値プロパティです。
これにより、開発者はデータベースへのラウンド・トリップの回数を削減できます。
関連項目:
文キャッシング
文キャッシングにより、最初の実行で作成されたサーバー・カーソルのキャッシングによる実行の前に、各SQL文またはPL/SQL文を解析する必要がなくなります。同じ文を後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスが向上します。
文キャッシングによるパフォーマンスの向上を得るために、繰り返し実行される文のみをキャッシュすることをお薦めします。さらに、SQL文またはPL/SQL文では、リテラル値ではなくパラメータを使用してください。これにより、文キャッシングが有効になります。これは、後続の実行でパラメータ値が異なる場合でも、パラメータ化された文から解析された情報は再利用できるためです。ただし、文のリテラル値が異なる場合、解析された情報は、後続の文にも同じリテラル値がないかぎり、再使用できません。
文キャッシングの接続文字列属性
次の接続文字列属性は、ODP.NET文キャッシング機能の動作を制御します。
-
StatementCacheSizeこの属性は、ODP.NET文キャッシングを有効化または無効化します。デフォルトでは、この属性は
0(無効)に設定されます。0より大きい値に設定すると、ODP.NET文キャッシングが有効になり、指定された値は接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。自動チューニングを有効にすると、文キャッシングも有効になります。その場合、
Statement Cache Sizeは自動的に構成されます。 -
StatementCachePurgeこの属性は、接続がクローズされた場合、または接続プールに戻された場合にキャッシュされるすべての文を消去する方法を提供します。デフォルトでは、この属性は
falseに設定されています。つまり、接続がプールに戻されてもカーソルは解放されません。
レジストリを使用した文キャッシングの有効化
アプリケーションを変更せずに、システムで実行しているすべての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の構成」を参照してください。文キャッシングのメソッドおよびプロパティ
次のプロパティおよびメソッドは、文キャッシングが有効な場合のみ当てはまります。
-
OracleCommand.AddToStatementCacheプロパティ文キャッシングが有効な場合、このプロパティを
trueに設定すると、文の実行時にキャッシュに文が追加されます。デフォルトでは、このプロパティはtrueに設定されています。文キャッシングが無効な場合、またはこのプロパティがfalseに設定されている場合、実行された文はキャッシュされません。 -
OracleConnection.PurgeStatementCacheメソッドこのメソッドは、特定の接続に関連付けられたデータベースでオープンしているカーソルをすべてクローズすることで、キャッシュされた文をすべて消去します。このコールの後も、文キャッシングは有効です。
自動チューニング
ODP.NETアプリケーションの自動チューニングを行ってパフォーマンスを最適化することができます。ODP.NETは実行時のアプリケーション問合せを動的に監視します。
ノート:
Pooling接続文字列属性がfalseに設定されている場合、アプリケーションの自動チューニングは実行されません。また、自動チューニングは.NETストアド・プロシージャではサポートされません。
文キャッシュ・サイズ(StatementCacheSize)は、アプリケーションによって実行される文を監視することで自動的にチューニングされます。次の各項では、アプリケーションの自動チューニングについて説明します。
文キャッシングの自動チューニング
文キャッシングを使用すると、各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に設定します。
関連項目:
アプリケーションの自動チューニングの有効化または無効化
ODP.NETアプリケーションの自動チューニングはデフォルトで有効になっています。アプリケーションの自動チューニングを有効化または無効化するには、次のいずれかの方法を使用します。
-
自動チューニングの接続文字列属性
Self Tuning接続文字列属性を変更すると、特定の接続プールについてアプリケーションの自動チューニングを有効化または無効化できます。Self Tuningのデフォルト値はtrueです。 -
Windowsレジストリ
次のレジストリ・エントリを変更すると、ODP.NETの特定のバージョンについてアプリケーションの自動チューニングを有効化または無効化できます。
HKLM\Software\Oracle\ODP.NET\version\SelfTuningSelfTuningキーの種類は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が使用されます。
最適化のための変更のトレース
自動チューニングによる最適化のための変更をアプリケーションでトレースできます。StatementCacheSizeに加えられたすべての変更がトレースされます。エラーがあれば、それもトレースされます。
自動チューニングのトレースに使用されるTraceLevelは、管理対象外ODP.NETの場合は64です。管理対象ODP.NETおよびODP.NET Coreでは、TraceLevel 7を使用します。
関連項目:
TraceLevel値の詳細は、表2-3を参照