ベース・クラス、プロバイダ・ファクトリ・クラスおよびDbDataSource

ベース・クラスおよびプロバイダ・ファクトリ・クラス

ADO.NETでは、データ・クラスはSystem.Data.Commonネームスペースで定義されたベース・クラスから導出されます。開発者は、プロバイダ・ファクトリ・クラスを使用して、これらのベース・クラスのプロバイダ固有のインスタンスを作成できます。

プロバイダ・ファクトリ・クラスでは、汎用データ・アクセス・コードによって、最小限のデータ・ソース固有コードで複数のデータ・ソースへアクセスできます。これにより、複数のデータ・ソースにアクセスするアプリケーションで現在使用されている条件付きロジックの多くを削減できます。

Oracle Data Provider for .NETを使用すると、OracleClientFactoryクラスを戻し、インスタンス化できます。これにより、ベース・クラスを継承する次のODP.NETクラスのインスタンスを作成するアプリケーションが有効になります。

表3-1 ADO.NETベース・クラスを継承するODP.NETクラス

ODP.NETクラス ADO.NET ベース・クラスから継承

OracleClientFactory

DbProviderFactory

OracleCommand

DbCommand

OracleCommandBuilder

DbCommandBuilder

OracleConnection

DbConnection

OracleConnectionStringBuilder

DbConnectionStringBuilder

OracleDataAdapter

DbDataAdapter

OracleDataReader

DbDataReader

OracleDataSourceEnumerator

DbDataSourceEnumerator

OracleException

DbException

OracleParameter

DbParameter

OracleParameterCollection

DbParameterCollection

OracleTransaction

DbTransaction

一般に、アプリケーションはいまだOracle固有の接続文字列、SQLまたはストアド・プロシージャ・コールを必要としており、ODP.NETからのファクトリを使用することを宣言します。

DbDataSource

ODP.NET Coreでは、OracleDataSourceクラスを介したADO.NET DbDataSource抽象化がサポートされています。新しいOracleDataSourceクラスでは、OracleConnectionOracleCommandの使用のかわりに、接続を取得しコマンドを直接実行できます。

このクラスではすべてのOracleデータベース接続構成がカプセル化されるため、OracleDataSourceは移植可能であり、依存性インジェクションに接続ファクトリとして登録できます。これは、Oracleデータベースに接続するときに、プロバイダを把握できないコードを使用する必要がある場合に最適です。

OracleDataSourceにはコンストラクタがありません。それは、OracleDataSourceBuilderクラスまたはOracleClientFactory.CreateDataSource(string connectionString)メソッドを使用して作成する必要があります。

ODP.NETでは、多くの接続構成オプションは、接続文字列で使用できません。これらの構成オプションが必要な場合は、開発者が、OracleDataSourceBuilderを使用した後に、それからOracleDataSourceを構築します。

ODP.NET Core 23.8で、.NET 8ランタイム以上でのOracleDataSourceOracleDataSourceBuilderのサポートが開始されました。

OracleDataSourceの接続

OracleDataSourceは、同期式または非同期式でオープン接続やクローズ済接続を戻すことができます。これは、接続文字列を使用するコマンドおよびバッチ操作を作成することもできます。

OracleDataSourceのコード・サンプル:

OracleClientFactory factory = new OracleClientFactory();

// Create OracleDataSource
DbDataSource dataSource = new OracleDataSourceBuilder("user id=hr; 
password=<PASSWORD>; data source=oracle").Build();

// Create closed connection, which uses the connection string set on OracleDataSource
DbConnection connection = dataSource.CreateConnection();
connection.Open();

connection.Close();

// Alternatively, an OracleCommand can be created directly from the OracleDataSource, which will be ready to execute commands
DbCommand cmd = dataSource.CreateCommand("select * from employees");
DbDataReader rdr = command.ExecuteReader();
while (reader.Read())
{
  Console.WriteLine(reader.GetString(0));
}
reader.Close();


プーリングが有効になっている場合、各OracleDataSourceインスタンスでは、それ固有の対応する接続プールがあり、参照プロセスをスキップすることで接続をより速く分配できます。OracleDataSourceは特定の接続プールに対応付けられているため、OracleDataSourceは、一旦作成された後は不変です。ただし、OracleDataSourceから作成されたOracleConnectionsは可変です。

OracleDataSourceの接続では、接続プロパティが同じである場合でも、従来のOracleConnectionプールとは異なるプールが使用されます。同じ原則により、OracleConnection.ClearAllPools()は、OracleDataSourceオブジェクトによって保持されているプールには影響しません。OracleDataSourceには、それ固有のClearPool()メソッドがあります。OracleDataSourceが破棄されると、その対応するプールがクリアされます。

OracleDataSourceからOracleConnectionが作成された後は、その接続がクローズされるときに、そのプロパティを変更できます。ただし、一部の接続プロパティは、プールに一意の識別子を割り当てるために使用されます。これらのプロパティの1つ以上を変更すると、既存のOracleDataSourceプールからその接続が削除され、新しいプールが作成されるか、別の既存のプールが使用されます。

パスワードは、OracleDataSource.PasswordプロパティとOracleDataSource.ProxyPasswordプロパティによって更新できます。次に接続がオープンされたときに、そのユーザーの認証に、その新しいパスワードが使用されるようになります。これらのプロパティは、データベース・パスワードを更新しません。パスワードは、変更可能な唯一のOracleDataSourceプロパティです。

OracleDataSourceのパフォーマンス・カウンタ

ODP.NETパフォーマンス・カウンタでのプール名は、OracleDataSource接続の場合は"ODS: "という接頭辞が付きます("ODS: user id=HR; data source=oracle"など)。

接続文字列が同じである2つのOracleDataSourceインスタンスには、別々のプールがあります。プール名の値を、それぞれを一意に区別できるように設定することをお薦めします。プール名は、OracleConnection.PoolNameまたはOracleDataSourceBuilder.UsePoolNameによって設定できます。

開発者は、各プールに一意のプール名が付いていることを確認する必要があります。

プールを作成する前に、そのプール名を設定する必要があります。ODP.NETにより、プールが作成された後にそのプール名の値が使用されることはなく、エラーもスローされません。

OracleDataSourceの接続のイベント・コールバック

OracleConnectionプロパティと同様に、OracleDataSourceOracleDataSourceBuilderでは、イベント・コールバックを使用できます。それらのイベントの動作は、HAEventを除き、OracleConnectionとほぼ同じです。OracleConnection HAEventは静的です。つまり、これはすべてのOracleConnectionインスタンスに対してイベントを登録します。OracleDataSource HAEventは静的ではありません。これは、他のイベントと同様にインスタンス・ベースです。OracleDataSourceBuilderに登録されたHAEventは、すべての接続ではなく、OracleDataSourceから作成された接続にのみ影響します。

この表では、OracleConnectionOracleDataSourceおよびOracleDataSourceBuilderのイベント・プロパティとその共通動作または固有動作を示しています。

OracleConnectionのプロパティ OracleDataSourceのプロパティ OracleDataSourceのメソッド 動作の説明

ConnectionOpen

InfoMessage

StateChange

ConnectionOpen

InfoMessage

StateChange

UseConnectionOpenCallback

UseInfoMessageCallback

UseStateChangeCallback

OracleDataSourceによって作成されたすべてのOracleConnectionインスタンスにイベント・コールバックを適用します。その時点で、それは、OracleConnection自体でのそのイベントの設定と同じように動作するようになります。

Failover

Failover

UseFailoverCallback

動作はほぼ同じです。ただし、OracleConnection.Failoverは、OracleConnectionがオープンされている場合のみ設定できます。OracleDataSourceBuilder.Failoverは、OracleDataSourceから作成されたすべてのOracleConnectionsにイベントを適用します(それらが最初にクローズされている場合でも同様)。

HAEvent

N/A

N/A

静的であるため、これは、すべてのOracleConnectionインスタンスにコールバックを登録します。

N/A

HAEvent

UseHAEventCallback

インスタンスベースであるため、これは、OracleDataSourceによって作成されたOracleConnectionインスタンスのみにコールバックを登録します。

OracleDataSourceのコマンド

OracleDataSource.CreateCommand()は、OracleCommandから導出された、新しいOracleDataSourceCommandクラスを戻します。このクラスは、OracleCommandとほぼ同じように機能しますが、いくつか違いがあります。

まず、その接続オブジェクトにアプリケーションでアクセスできません。OracleDataSourceCommandは、実行コールの前に内部的に接続をオープンし、ExecuteReaderを除く実行の完了後にその接続をクローズします。このリーダーは、結果を取得するために、その接続を必要とします。リーダーがクローズされると接続がクローズされます。

アプリケーションは、通常は、それらのODP.NETで接続されている型すべて(LOBデータやLONGデータなど)の取得を延期します。このためには、将来データをフェッチできるようにその接続をオープン状態のままにする必要があります。接続されている型をOracleDataSourceCommandとともに、ExecuteReaderなしで使用する場合は、InitialLOBFetchSizeプロパティまたはInitialLONGFetchSizeプロパティを十分な大きさの値に設定して、すべての結果セットのLOBデータとLONGデータがただちに取得されるようにします。LOBデータやLONGデータが残っている場合に、アプリケーションがそれをフェッチしようとすると、例外がスローされます。

ノート:

OracleDataSourceCommandは、OracleDataAdapterと互換性がありません。

OracleDataSourceCommandは、OracleDataSource.CreateCommand()を介してのみ作成できます。

接続オブジェクトはOracleDataSourceからアクセスできないため、OracleDataSourceCommand.ConnectionプロパティとOracleDataSourceCommand.Transactionプロパティは、アクセスされるとInvalidOperationExceptionをスローします。

ExecuteNonQuery()の例

OracleDataSource ds = new OracleDataSourceBuilder("<CONNECTION STRING>").Build();
OracleCommand cmd = ds.CreateCommand("INSERT INTO mytable VALUES(0, 1)");
// ODP.NET internally opens a connection when ExecuteNonQuery is called
OracleDataReader rdr = cmd.ExecuteNonQuery();
// ODP.NET closes the connection after ExecuteNonQuery completes.

ExecuteReader()の例

OracleDataSource ds = new OracleDataSourceBuilder("<CONNECTION STRING>").Build();
OracleCommand cmd = ds.CreateCommand("SELECT * FROM mytable");
// ODP.NET internally opens a connection when ExecuteReader is called
OracleDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
    Console.WriteLine(rdr.GetString(0));
}
rdr.Close();
// ODP.NET closes the connection when the reader is closed.