ヘッダーをスキップ
Oracle Data Provider for .NET開発者ガイド
10g リリース2(10.2.0.2)
B31247-01
  目次へ
目次
索引へ
索引

前へ
前へ
 
次へ
次へ
 

Database Change Notificationサポート

Oracle Data Provider for .NETでは、Database Change Notificationをサポートする通知フレームワークが提供され、問合せの結果セット、スキーマ・オブジェクトまたはデータベースの状態に変更があったときにアプリケーションが通知を受け取れます。Database Change Notificationを使用すると、アプリケーションでは、クライアント側のキャッシュ妥当性(ADO.NET DataSetなど)を簡単に維持できます。


注意:

Database Change Notificationは、.NETストアド・プロシージャではサポートされません。

通知フレームワークを使用して、アプリケーションでは通知要求に対する登録済問い合せとして問合せ結果セットを指定し、この通知登録を作成して問合せ結果セットの妥当性を維持できます。問合せ結果セットに変更があれば、通知フレームワークがアプリケーションに通知します。


注意:

変更通知の内容は無効化メッセージと呼ばれます。これは、問合せ結果セットが現在無効であり、変更についての情報を提供していることを示します。

通知フレームワークにより提供される情報に基づき、アプリケーションはそれに応じた動作ができます。たとえば、アプリケーション内のローカルに格納されている、登録済問合せのデータのコピーをリフレッシュする必要がある場合があります。

データベースは、基礎となる表のデータが.NETクライアント上で使用されている場合、そのデータに加えられた変更をOracle Data Provider for .NETに通知します。


注意:

登録済オブジェクトがデータベースから削除され、同じ名前の新規オブジェクトが同じスキーマ内に作成される場合、再登録して新規作成されたオブジェクトの通知を受け取る必要があります。


参照:

Database Change Notificationに関する詳細は、『Oracle Databaseアプリケーション開発者ガイド-基礎編』を参照してください。

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

Database Change Notificationクラス

次のクラスは、Database Change Notificationサポートに関連付けられています。

  • OracleDependency

    アプリケーションとそれに関連するデータベース・イベントに基づいたOracleデータベース間の依存性を表します。これには依存性に関する情報が含まれており、指定のデータベース・イベントが発生した際にアプリケーションに通知する方法が提供されます。またOracleDependencyクラスでは、データベース通知をリスニングする通知リスナーも作成されます。各アプリケーション・ドメインには、データベース通知リスナーが1つのみあります。アプリケーション・プロセスが終了すると、この通知リスナーも終了します。

    アプリケーションとデータベースの間の依存性は、OracleDependencyオブジェクトの作成時には確立されません。依存性は、このOracleDependencyオブジェクトに関連付けられたコマンドの実行時に確立されます。そのコマンドの実行により、データベース内にデータベース変更通知登録が作成されます。

    データベース内で変更が発生すると、OracleDependencyオブジェクトのHasChangesプロパティがtrueに設定されます。さらに、イベント・ハンドラがOracleDependencyオブジェクトのOnChangeイベントで登録された場合、登録済イベント・ハンドラ関数が起動されます。

  • OracleNotificationRequest

    データベース内に登録される通知要求を表します。これには、要求に関する情報と通知のプロパティが含まれます。

  • OracleNotificationEventArgs

    指定されたデータベース・イベントが発生し、そのデータベース・イベントに関する詳細が含まれる際に通知に対して生成された、無効化メッセージを表します。

サポートされている操作

ODP.NET通知フレームワークでは、Database Change Notificationと連携して次のアクティビティがサポートされます。

  • 通知登録の作成

    • OracleDependencyインスタンスを作成してOracleCommandインスタンスにバインドします。

  • 複数の通知要求を1つの登録にグループ化

    • OracleDependency.AddCommandDependencyメソッドを使用します。

    • 同じOracleNotificationRequestインスタンスを使用してOracleCommand.Notification要求を設定します。

  • データベース変更通知の登録

    • OracleCommandを実行します。通知プロパティがNULLであるか、NotificationAutoEnlistがfalseである場合、通知は作成されません。

  • 通知登録の削除

    • OracleDependency.RemoveRegistrationメソッドを使用します。

    • 登録が作成される前に、OracleNotificationRequestインスタンス内にTimeoutプロパティを設定します。

    • 登録が作成される前に、OracleNotificationRequestインスタンス内のIsNotifiedOnceプロパティをtrueに設定します。データベース通知が送信されると、登録が削除されます。

  • 変更通知の永続性の確保

    • 配信前に、無効化メッセージがデータベース内で永続的にキューされるかどうかを指定します。無効化メッセージがデータベース内で永続的に保存されると、変更通知の送信が保証されます。無効化メッセージをメモリー内キューに保存すると、変更通知はより素早く受信できますが、データベースのシャットダウンまたはクラッシュ時に失われる可能性があります。

  • 次の項目を含む通知情報の取得:

    • 変更されたオブジェクト名

    • 変更されたオブジェクトのスキーマ名

    • 通知を発生させるデータベース・イベント(挿入、削除など)

    • 変更されたオブジェクト行のRowID

      Oracle SQLでは、ROWIDTOCHAR(ROWID)およびROWIDTONCHAR(ROWID)関数により、ROWID値がそれぞれVARCHAR2およびNVARCHARデータ型に変換されます。 これらの関数がSQL文内で使用されている場合、ROWIDはデータベース変更通知コールバックに渡されるOracleNotificationEventArgsオブジェクトには戻されません。

  • リスナー・ポート番号の定義

    デフォルトでは、静的なOracleDependency.Portプロパティは-1に設定されています。これは、ODP.NETがアプリケーション実行時に初めてデータベース変更通知要求を登録した場合、ODP.NETがランダムに選択されたポート上でリスニングすることを示します。

    ODP.NETは、1つのポート上でリスニングするリスナーをアプリケーション・ドメイン内に1つのみ作成します。 ODP.NETでリスナーが起動されると、ポート番号を変更できません。静的なOracleDependency.Portプロパティに対して変更を加えると、リスナーがすでに作成済である場合はエラーが発生します。

    デフォルトにより、Windows XP Service Pack 2以上のすべてのインストレーションにおいて、Windowsファイアウォールは、着信接続に対するほとんどすべてのTCPネットワーク・ポートをブロックできます。したがって、Windows XP Service Pack 2以上でDatabase Change Notificationを適切に機能させるには、特定の実行可能ファイルで特定のポートをオープンできるように、Windowsファイアウォールを適切に設定する必要があります。


    参照:

    Windowsファイアウォールの設定の詳細は、Windows用の『Oracle Databaseプラットフォーム・ガイド』を参照してください。

通知登録の要件

接続済ユーザーは、通知登録を作成する、CHANGE NOTIFICATION権限を持っている必要があります。

このSQL文により、CHANGE NOTIFICATION権限が付与されます。

grant change notification to user name

このSQL文により、CHANGE NOTIFICATION権限が取り消されます。

revoke change notification from user name

Database Change Notificationの使用

この項では、アプリケーションで実行する必要がある処理、およびアプリケーションがDatabase Change Notificationを使用して登録済問合せ結果セットから変更結果の通知を受け取る際の処理フローを説明します。

アプリケーション側の手順

アプリケーションで必要になる手順は次のとおりです。

  1. OracleDependencyインスタンスを作成します。

  2. データベースの変更が検出されたときにアプリケーションでイベント・ハンドラを起動する場合は、イベント・ハンドラをOracleDependency.OnChangeイベント・プロパティに割り当てます。それ以外の場合は、OracleDependencyオブジェクトのHasChangesプロパティに対してポーリングするよう、アプリケーションで選択できます。このイベント・ハンドラは、変更通知を受け取ると起動されます。

  3. リスナーがリスニングを行うポート番号を設定します。アプリケーションでは、1つの通知リスナーがリスニングを行うポート番号を指定できます。アプリケーションでポート番号を指定しないと、ランダムな番号がリスナーで使用されます。

  4. 実際に実行される問合せを含むOracleCommandインスタンスにOracleDependencyインスタンスをバインドします。内部的に、データベース変更通知要求(OracleNotificationRequestインスタンス)が作成され、OracleCommand.Notificationプロパティに割り当てられます。

通知処理フロー

  1. 通知要求に関連付けられたコマンドが実行されると、データベース内に通知登録が作成されます。コマンドの実行により、結果セットが戻される、またはPL/SQLストアド・プロシージャのREFカーソルが1つ以上含まれる必要があります。

  2. ODP.NETは、最初に成功した通知登録上でアプリケーション・リスナーを開始します。

  3. データベース内で登録に関連する変更が発生すると、OracleDependency.OnChangeイベント・プロパティに割り当てられたイベント・デリゲート経由でアプリケーションに通知されるか、またはアプリケーションでOracleDependency.HasChangesプロパティをポーリングできます。

次の例は、データベース変更通知機能を示しています。

// Database Setup
// NOTE: unless the following SQL command is executed,
// ORA-29972 will be obtained from running this sample
/*
grant change notification to scott;
*/
using System;
using System.Threading;
using System.Data;
using Oracle.DataAccess.Client;
using Oracle.DataAccess.Types;

//This sample shows the database change notification feature in ODP.NET.
//Application specifies to get a notification when emp table is updated.
//When emp table is updated, the application will get a notification
//through an event handler.
namespace NotificationSample
{
  public class MyNotificationSample
  {
    public static bool IsNotified = false;

    public static void Main(string[] args)
    {
      //To Run this sample, make sure that the change notification privilege
      //is granted to scott.
      string constr = "User Id=scott;Password=tiger;Data Source=oracle";
      OracleConnection con = null;
      OracleDependency dep = null;

      try
      {
        con = new OracleConnection(constr);
        OracleCommand    cmd = new OracleCommand("select * from emp", con);
        con.Open();

        // Set the port number for the listener to listen for the notification
        // request
        OracleDependency.Port = 1005;

        // Create an OracleDependency instance and bind it to an OracleCommand
        // instance.
        // When an OracleDependency instance is bound to an OracleCommand
        // instance, an OracleNotificationRequest is created and is set in the
        // OracleCommand's Notification property. This indicates subsequent
        // execution of command will register the notification.
        // By default, the notification request is using the Database Change
        // Notification.
        dep = new OracleDependency(cmd);

        // Add the event handler to handle the notification. The
        // OnMyNotification method will be invoked when a notification message
        // is received from the database
        dep.OnChange +=
          new OnChangeEventHandler(MyNotificationSample.OnMyNotificaton);

        // The notification registration is created and the query result sets
        // associated with the command can be invalidated when there is a
        // change.  When the first notification registration occurs, the
        // notification listener is started and the listener port number
        // will be 1005.
        cmd.ExecuteNonQuery();

        // Updating emp table so that a notification can be received when
        // the emp table is updated.
        // Start a transaction to update emp table
        OracleTransaction txn = con.BeginTransaction();
        // Create a new command which will update emp table
        string updateCmdText =
          "update emp set sal = sal + 10 where empno = 7782";
        OracleCommand updateCmd = new OracleCommand(updateCmdText, con);
        // Update the emp table
        updateCmd.ExecuteNonQuery();
        //When the transaction is committed, a notification will be sent from
        //the database
        txn.Commit();
      }
      catch (Exception e)
      {
        Console.WriteLine(e.Message);
      }

      con.Close();
      // Loop while waiting for notification
      while(MyNotificationSample.IsNotified == false)
      {
        Thread.Sleep(100);
      }
    }

    public static void OnMyNotificaton(object src,
      OracleNotificationEventArgs arg)
    {
      Console.WriteLine("Notification Received");
      DataTable changeDetails = arg.Details;
      Console.WriteLine("Data has changed in {0}",
        changeDetails.Rows[0]["ResourceName"]);
      MyNotificationSample.IsNotified = true;
    }
  }
}

ベスト・プラクティスの指針とパフォーマンス上の考慮点

この項では、Database Change NotificationおよびODP.NET通知フレームワークの使用上、役立つ指針を提供し、パフォーマンスの影響について説明します。変更通知登録が行われると、データベース・メモリー、ストレージまたはネットワーク・リソース(あるいはそれらの組合せ)が消費されます。リソースの消費量は、さらに、無効化メッセージのボリュームとサイズに依存します。多数の中間層クライアントに適切に対応するために、クライアントで次のベスト・プラクティスを実装することをお薦めします。

  • 表の数を減らし、多くを読取り専用にすること

    登録済のオブジェクト数を減らし、多くを読取り専用にしてください。また無効化の頻度を下げてください。オブジェクトの揮発性がきわめて高い場合、多数の無効化通知が送信され、大量のスペース(メモリー内またはディスク上)が必要になる可能性があります。これは、オブジェクトが多数登録されている場合にも当てはまります。

  • 各表で更新される行の数を減らすこと

    トランザクションでは、登録済の表中の行のうち、少数のみを更新(または挿入、削除)するようにしてください。任意の表で、単一のトランザクション内で更新する行が多すぎると、データベース・リソースに応じて、表全体が無効化される可能性があります。

    この方針により、単一の無効化メッセージのサイズが抑制され、無効化キュー用のディスク・ストレージが削減されます。


参照:

Database Change Notificationに関する詳細は、『Oracle Databaseアプリケーション開発者ガイド-基礎編』を参照してください。