プライマリ・コンテンツに移動
Oracle® Data Provider for .NET開発者ガイド
ODAC 12c リリース4 (12.1.0.2) for Microsoft Windows
E72575-01
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

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 11gリリース(11.1)以上のSystem.Transactionsスコープでオープンされた最初の接続に対しては、ローカル・トランザクションが作成されます。2番目の接続がオープンされると、このトランザクションは自動的に分散トランザクションに昇格します。この機能は、パフォーマンスとスケーラビリティの向上を実現します。

TransactionScopeServicedComponentなどのトランザクション・コンテキスト内で作成された接続は、様々なリリースの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回目の接続を試みると、例外がスローされます。

Oracle Database 11gリリース1(11.1)より前のインスタンスに接続するアプリケーションについては、「旧リリースのデータベースにおけるローカル・トランザクション・サポート」を参照してください。この項では、Promotable Transactionの設定を使用してODP.NETの動作を制御する方法について説明します。

アプリケーションがSystem.Transactionsを使用する場合は、enlist接続文字列属性をtrue(デフォルト)またはdynamicのいずれかに設定する必要があります。ただし、自動登録するにはenlist=trueである必要があるため、TransactionScopeとともにenlist=dynamicを使用することはできません。

ODP.NETは、分散トランザクションを使用するアプリケーション用に、次のSystem.Transactionsプログラミング・モデルをサポートしています。

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);
    }
  }
}

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);
    }
  }
}

関連項目:

「EnlistTransaction」

旧リリースのデータベースにおけるローカル・トランザクション・サポート

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のバージョンを使用するすべてのアプリケーションに適用します。

パラメータ・バインド

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型として戻されます。DbTypeOracleDbTypeの両方のプロパティを設定してからコマンドを実行した場合は、最後の設定が有効になります。

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

  • ExecuteReader

  • ExecuteNonQuery

  • ExecuteScalar

アプリケーションは、出力パラメータの値をバインドできません。出力パラメータ値のバインドはODP.NETによって行われます。値オブジェクトが作成され、オブジェクトがOracleParameter Valueプロパティに移入されます。

ファンクションに対して位置別(デフォルト)でバインドする場合、最初に他のパラメータより前にバインドされる戻り値がODP.NETに必要です。

この項の内容は次のとおりです。

OracleDbTypeの列挙型

OracleDbTypeの列挙値は、OracleParameterオブジェクトのOracleDbTypeを明示的に指定する際に使用されます。

表3-5では、すべてのOracleDbTypeの列挙値と、それぞれの列挙値の説明をリストしています。

表3-5 OracleDbTypeの列挙値

メンバー名 説明

Array

Oracleコレクション(VArrayまたはネストされた表)

ODP.NET管理対象ドライバでは使用できません

BFile

Oracle BFILE

BinaryFloat

Oracle BINARY_FLOAT

BinaryDouble

Oracle BINARY_DOUBLE

Blob

Oracle BLOB

Boolean

Oracle BOOLEAN

ODP.NET管理対象ドライバでは使用できません

Byte

byte

Char

Oracle CHAR

Clob

Oracle CLOB

Date

Oracle DATE

Decimal

Oracle NUMBER

Double

8バイトのFLOAT

Int16

2バイトのINTEGER

Int32

4バイトのINTEGER

Int64

8バイトのINTEGER

IntervalDS

Oracle INTERVAL DAY TO SECOND

IntervalYM

Oracle INTERVAL YEAR TO MONTH

Long

Oracle LONG

LongRaw

Oracle LONG RAW

NChar

Oracle NCHAR

Object

Oracle Object型

ODP.NET管理対象ドライバでは使用できません

NClob

Oracle NCLOB

NVarchar2

Oracle NVARCHAR2

Raw

Oracle RAW

Ref

Oracle REF

ODP.NET管理対象ドライバでは使用できません

RefCursor

Oracle REF CURSOR

Single

4バイトのFLOAT

TimeStamp

Oracle TIMESTAMP

TimeStampLTZ

Oracle TIMESTAMP WITH LOCAL TIME ZONE

TimeStampTZ

Oracle TIMESTAMP WITH TIME ZONE

Varchar2

Oracle VARCHAR2

XmlType

Oracle XMLType



注意:

PL/SQLのLONG、LONG RAW、RAWおよびVARCHARデータ型は、32512バイトまでのサイズにバインドできます。

DbType、OracleDbTypeおよび.NETタイプの判断

この項では、OracleParameterクラス内のSystem.Data.DbTypeOracleDbTypeおよびValueのプロパティからの判断を説明します。

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

OracleDbTypeからのDbTypeの判断

OracleParameterクラスでは、OracleDbTypeの値を指定すると、表3-6に示されているとおりDbTypeの値が判断されます。

表3-6 OracleDbTypeからのSystem.Data.DbTypeの判断

OracleDbType System.Data.DbType

Array

Object

BFile

Object

Blob

Object

BinaryFloat

Single

BinaryDouble

Double

Boolean

Boolean

Byte

Byte

Char

StringFixedLength

Clob

Object

Date

Date

Decimal

Decimal

Double

Double

Int16

Int16

Int32

Int32

Int64

Int64

IntervalDS

Object

IntervalYM

Int64

Long

String

LongRaw

Binary

NChar

StringFixedLength

NClob

Object

NVarchar2

String

Object

Object

Raw

Binary

Ref

Object

RefCursor

Object

Single

Single

TimeStamp

DateTime

TimeStampLTZ

DateTime

TimeStampTZ

DateTime

Varchar2

String

XmlType

String


DbTypeからのOracleDbTypeの判断

OracleParameterクラスでは、DbTypeの値を指定すると、表3-7に示されているとおりOracleDbTypeの値が判断されます。

表3-7 DbTypeからのOracleDbTypeの判断

System.Data.DbType OracleDbType

Binary

Raw

Boolean

Boolean

Byte

Byte

Currency

サポート対象外

Date

Date

DateTime

TimeStamp

Decimal

Decimal

Double

Double

Guid

サポート対象外

Int16

Int16

Int32

Int32

Int64

Int64

Object

Object

Sbyte

サポート対象外

Single

Single

String

Varchar2

StringFixedLength

Char

Time

TimeStamp

UInt16

サポート対象外

UInt32

サポート対象外

Uint64

サポート対象外

VarNumeric

サポート対象外


ValueからのDbTypeおよびOracleDbTypeの判断

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

表3-8は、Valueの型が.NET Frameworkデータ型の1つの場合における、ValueプロパティからのDbTypeプロパティおよびOracleDbTypeプロパティの判断を示します。

表3-8 Value(.NETデータ型)からのDbTypeおよびOracleDbTypeの判断

Value(.NETデータ型) System.Data.DbType OracleDbType

Boolean

Boolean

Boolean

Byte

Byte

Byte

Byte[]

Binary

Raw

Char / Char []

String

Varchar2

DateTime

DateTime

TimeStamp

Decimal

Decimal

Decimal

Double

Double

Double

Float

Single

Single

Int16

Int16

Int16

Int32

Int32

Int32

Int64

Int64

Int64

IOracleCustomType

Object

Object

Single

Single

Single

String

String

Varchar2

TimeSpan

Object

IntervalDS



注意:

DbTypeまたはOracleDbTypeプロパティを指定せずに、OracleParameterクラスの値としてその他の.NET Frameworkデータ型を使用すると、例外が発生します。これは、その他の.NET Frameworkデータ型からのDbTypeプロパティおよびOracleDbTypeプロパティの判断がサポートされていないためです。

表3-9は、Valueの型がOracle.DataAccess.Typesの1つの場合における、ValueプロパティからのDbTypeプロパティおよびOracleDbTypeプロパティの判断を示しています。

表3-9 Value(ODP.NETタイプ)からのDbTypeおよびOracleDbTypeの判断

Value(Oracle.DataAccess.Types) System.Data.DbType OracleDbType

OracleBFile

Object

BFile

OracleBinary

Binary

Raw

OracleBlob

Object

Blob

OracleBoolean

Boolean

Boolean

OracleClob

Object

Clob

OracleDate

Date

Date

OracleDecimal

Decimal

Decimal

OracleIntervalDS

Object

IntervalDS

OracleIntervalYM

Int64

IntervalYM

OracleRef

Object

Ref

OracleRefCursor

Object

RefCursor

OracleString

String

Varchar2

OracleTimeStamp

DateTime

TimeStamp

OracleTimeStampLTZ

DateTime

TimeStampLTZ

OracleTimeStampTZ

DateTime

TimeStampTZ

OracleXmlType

String

XmlType


PL/SQL連想配列バインド

ODP.NETは、PL/SQL連想配列(従来のPL/SQL索引付き表)バインドをサポートしています。

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

  • CollectionType

    このプロパティは、PL/SQL連想配列にバインドするために、OracleCollectionType.PLSQLAssociativeArrayに設定する必要があります。

  • ArrayBindSize

    このプロパティは、固定長の要素タイプ(Int32など)の場合は無視されます。

    可変長の要素タイプ(Varchar2など)の場合、ArrayBindSizeプロパティ内の各要素は、Valueプロパティ内の対応する要素のサイズを指定します。

    Outputパラメータ、InputOutputパラメータおよび戻り値の場合、このプロパティは、可変長の変数に対して指定する必要があります。

    ODP.NETの各配列要素には、1つの要素ごとに文字を2GBまで格納でき、バイナリ・データの場合は4GBまで格納できます。

  • ArrayBindStatus

    このプロパティは、OracleParameter.Valueプロパティ内の各要素の実行ステータスを指定します。

  • Size

    このプロパティは、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連想配列としてバインドします。Param1Inパラメータ、Param2InputOutputパラメータ、Param3Outputパラメータとしてバインドします。

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プロパティは、配列内の対応する各値の最大サイズを指定する整数の配列です。ArrayBindSizeプロパティは、OracleParameterオブジェクトのSizeプロパティに類似していますが、ArrayBindSizeプロパティは配列内の各値のサイズを指定するという点が異なります。

    アプリケーションは、実行前にArrayBindSizeプロパティを移入する必要があります。ODP.NETは、実行後にArrayBindSizeプロパティを移入します。

    ArrayBindSizeプロパティは、ClobBlobVarchar2など、可変長のパラメータ・タイプにのみ使用されます。Unicode文字列タイプのバイナリ・データ型および文字の場合、サイズはバイトで表されます。文字列タイプのカウントには、終了文字は含まれません。サイズが明示的に設定されていない場合は、値の実際のサイズから推測されます。出力パラメータの場合、各値のサイズはODP.NETにより設定されます。固定長のデータ型の場合、ArrayBindSizeプロパティは無視されます。

  • ArrayBindStatus

    ArrayBindStatusプロパティは、パラメータの配列内の対応する各値のステータスを指定するOracleParameterStatus値の配列です。このプロパティは、OracleParameterStatusプロパティに類似していますが、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-10に、OracleParameterStatusの列挙値をリストします。

表3-10 OracleParameterStatusのメンバー

メンバー名 説明

Success

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

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

NullFetched

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

NullInsert

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

Truncation

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


バッチ処理

OracleDataAdapter.Updateメソッドがコールされると、OracleDataAdapter UpdateBatchSizeプロパティではバッチ処理が有効になります。UpdateBatchSizeは、各ラウンドトリップで、Oracle Databaseを更新するDataSet行数を示す数値プロパティです。

これにより、開発者はデータベースへのラウンド・トリップの回数を削減できます。


関連項目:

「UpdateBatchSize」

文キャッシング

文キャッシングにより、最初の実行で作成されたサーバー・カーソルのキャッシングによる実行の前に、各SQL文またはPL/SQL文を解析する必要がなくなります。同じ文を後で実行する場合、カーソルから解析された情報を再利用して、文を解析せずに実行することで、パフォーマンスが向上します。

文キャッシングによるパフォーマンスの向上を得るために、繰り返し実行される文のみをキャッシュすることをお薦めします。さらに、SQL文またはPL/SQL文では、リテラル値ではなくパラメータを使用してください。これにより、文キャッシングが有効になります。これは、後続の実行でパラメータ値が異なる場合でも、パラメータ化された文から解析された情報は再利用できるためです。ただし、文のリテラル値が異なる場合、解析された情報は、後続の文にも同じリテラル値がないかぎり、再使用できません。

文キャッシングの接続文字列属性

次の接続文字列属性は、ODP.NET文キャッシング機能の動作を制御します。

  • Statement Cache Size

    この属性は、ODP.NET文キャッシングを有効化または無効化します。デフォルトでは、この属性は0(無効)に設定されます。0より大きい値に設定すると、ODP.NET文キャッシングが有効になり、指定された値は接続用にキャッシュできる文の最大数として使用されます。指定された最大キャッシュ・サイズまで接続がキャッシュされると、最低使用頻度のカーソルが解放され、新しく作成されたカーソルをキャッシュするためのスペースが確保されます。

    自動チューニングを有効にすると、文キャッシングも有効になります。その場合、Statement Cache Sizeは自動的に構成されます。

  • Statement Cache Purge

    この属性は、接続がクローズされた場合、または接続プールに戻された場合にキャッシュされるすべての文を消去する方法を提供します。デフォルトでは、この属性は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メソッド

    このメソッドは、特定の接続に関連付けられたデータベースでオープンしているカーソルをすべてクローズすることで、キャッシュされた文をすべて消去します。このコールの後も、文キャッシングは有効です。

接続と文キャッシング

文キャッシングは、接続ごとに個別に管理されます。このため、異なる接続で同じ文を実行するには、接続ごとに1回消去して、接続ごとに個別のカーソルをキャッシュする必要があります。

プーリングと文キャッシング

プーリングと文キャッシングは同時に使用できます。接続プーリングが有効で、Statement Cache Purge属性がfalseに設定されている場合、個別の接続で実行される文は、プールされた接続の存続期間を通じてキャッシュされます。

Statement Cache Purge属性がtrueに設定されている場合は、接続がプールに戻されたときに、キャッシュされたすべてのカーソルが解放されます。接続プーリングが無効な場合、カーソルは接続の存続中にキャッシュされますが、OracleConnectionオブジェクトがクローズまたは処理されたときにはクローズされます。

自動チューニング

ODP.NETアプリケーションの自動チューニングを行ってパフォーマンスを最適化することができます。ODP.NETは実行時のアプリケーション問合せを動的に監視します。


注意:

Pooling接続文字列属性がfalseに設定されている場合、アプリケーションの自動チューニングは実行されません。また、自動チューニングは.NETストアド・プロシージャではサポートされません。

文キャッシュ・サイズ(StatementCacheSize)は、アプリケーションによって実行される文を監視することで自動的にチューニングされます。次の各項では、アプリケーションの自動チューニングについて説明します。

文キャッシングの自動チューニング

文キャッシングを使用すると、各SQL文またはPL/SQL文を実行前に再解析する必要がなくなり、パフォーマンスが向上します。

アプリケーションの自動チューニングが有効な場合、ODP.NETは文キャッシュ・サイズの最適な値を決定するためにアプリケーションの動作を継続的に監視します。接続文字列、構成ファイルまたはレジストリに指定した文キャッシュ・サイズの値は無視されます。

アプリケーションが最初に初期化されるときは、文キャッシュ・サイズのデフォルト値が使用されます。アプリケーションが文を実行するのと並行して、ODP.NETは文キャッシュ・サイズの値の自動チューニングに使用される統計を収集します。文キャッシュ・サイズの自動チューニングを行うとパフォーマンスが向上します。


注意:

文キャッシングの利点を最大限活用するには、文の実行ごとに異なるインライン値で文を動的に生成しないでください。かわりに、パラメータ化されたコマンドを使用して、実行およびキャッシュする必要がある一意の文の数を最小限にします。これは、パラメータ値や文の実行回数にかかわらず、一意の各コマンド・テキストでキャッシュする必要のある文が1つのみになるためです。

接続ごとにキャッシュできる文の最大数は、MaxStatementCacheSize構成属性によって決まります。MaxStatementCacheSizeの値は、WindowsレジストリまたはXML構成ファイルで指定できます。

MaxStatementCacheSize設定は、キャッシュされる文の数やオープンしているカーソル数を制限する場合に便利です。これは、キャッシュされる文は、サーバーでオープンになっているカーソルと等しいためです。このため、MaxStatementCacheSizeをデータベースのMAX_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\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が使用されます。

最適化のための変更のトレース

自動チューニングによる最適化のための変更をアプリケーションでトレースできます。StatementCacheSizeに加えられたすべての変更がトレースされます。エラーがあれば、それもトレースされます。

自動チューニングのトレースに使用されるTraceLevel64です。


関連項目:

TraceLevel値の詳細は、表2-1「構成属性」を参照してください。