次の方法で共有


WCF サービス モデル 1 を使用して Oracle データベース変更通知を受信する

このトピックでは、Oracle データベースからクエリ通知メッセージを受信するように Oracle データベース アダプターを構成する方法について説明します。 通知を示すには、"処理済み" 列を含むテーブル ACCOUNTACTIVITY を検討してください。 このテーブルに新しいレコードが挿入されると、Status 列の値は 'n' に設定されます。 "処理済み" 列を持つすべてのレコードを 'n' として取得する SQL ステートメントを使用して通知を登録することで、通知を受信するようにアダプターを構成できます。 これを行うには、 NotificationStatement バインディング プロパティに SQL ステートメントを指定します。 アダプター クライアントは、通知を受信すると、Oracle データベースで後続のタスクを実行するロジックを含めることができます。 この例では、わかりやすくするために、アダプター クライアントは、"処理済み" 列を持つテーブル内のすべてのレコードを 'n' として一覧表示します。

Oracle データベース アダプターのバインド プロパティを使用した通知の構成

次の表は、Oracle データベースからの通知の受信を構成するために使用する Oracle Database アダプターのバインド プロパティをまとめたものです。 通知を受信するには、.NET アプリケーションの実行中にこれらのバインド プロパティを指定する必要があります。

バインディングプロパティ 説明
InboundOperationType 実行する受信操作を指定します。 通知メッセージを受信するには、これを [通知] に設定します。
NotificationPort Oracle データベースからのデータベース変更通知を受け取るために、ODP.NET がリッスンする必要があるポート番号を指定します。
NotificationStatement クエリ通知の登録に使用する SELECT ステートメントを指定します。 アダプターは、指定した SELECT ステートメントの結果セットが変更された場合にのみ通知メッセージを取得します。
NotifyOnListenerStart リスナーの起動時にアダプターがアダプター クライアントに通知を送信するかどうかを指定します。

これらのプロパティの詳細については、「 Oracle Database のバインド プロパティを構成する」を参照してください。 Oracle データベース アダプターを使用して Oracle データベースから通知を受信する方法の詳細については、詳細を参照してください。

WCF サービス モデルを使用した通知の構成

WCF サービス モデルを使用して通知を受信するには、次の手順を実行する必要があります。

  • アダプターによって公開されるメタデータから 、通知 操作用の WCF サービス コントラクト (インターフェイス) を生成します。 これを行うには、アダプター サービス参照の追加プラグインを使用できます。

  • ACCOUNTACTIVITY テーブルに対する Select 操作用の WCF クライアントを生成します。 これを行うには、アダプター サービス参照の追加プラグインを使用できます。

  • このインターフェイスから WCF サービスを実装します。

  • サービス ホスト (System.ServiceModel.ServiceHost) を使用して、この WCF サービスをホストします。

WCF サービス コントラクトとクラス

アダプター サービス参照の追加プラグインを使用して、WCF サービス コントラクト (インターフェイス) と 通知 操作のサポート クラスを作成できます。 WCF サービス コントラクトの生成の詳細については、「 Oracle Database ソリューション成果物の WCF クライアントまたは WCF サービス コントラクトを生成する」を参照してください。

WCF サービス コントラクト (インターフェイス)

次のコードは、 通知 操作用に生成された WCF サービス コントラクト (インターフェイス) を示しています。

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03", ConfigurationName="Notification_OperationGroup")]
public interface Notification_OperationGroup {

    // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/Notification/) of message Notification
    // does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="http://Microsoft.LobServices.OracleDB/2007/03/Notification")]
    void Notification(Notification request);
}

メッセージ コントラクト

通知操作のメッセージ コントラクトを次に示します。

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Notification", WrapperNamespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", IsWrapped=true)]
public partial class Notification {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=0)]
    public microsoft.lobservices.oracledb._2007._03.Notification.NotificationDetails[] Details;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=1)]
    public string Info;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=2)]
    public string[] ResourceNames;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=3)]
    public string Source;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://Microsoft.LobServices.OracleDB/2007/03/Notification/", Order=4)]
    public string Type;

    public Notification() {
    }

    public Notification(microsoft.lobservices.oracledb._2007._03.Notification.NotificationDetails[] Details, string Info, string[] ResourceNames, string Source, string Type) {
        this.Details = Details;
        this.Info = Info;
        this.ResourceNames = ResourceNames;
        this.Source = Source;
        this.Type = Type;
    }
}

WCF サービス クラス

アダプター サービス参照の追加プラグインは、サービス コントラクト (インターフェイス) から実装された WCF サービス クラスのスタブを持つファイルも生成します。 ファイルの名前はOracleDBBindingService.cs。 このクラスに 通知 操作を直接処理するロジックを挿入できます。 次のコードは、アダプター サービス参照プラグインの追加によって生成される WCF サービス クラスを示しています。

namespace OracleDBBindingNamespace {

    public class OracleDBBindingService : Notification_OperationGroup {

        // CODEGEN: Generating message contract since the wrapper namespace (http://Microsoft.LobServices.OracleDB/2007/03/Notification/) of message Notification
        // does not match the default value (http://Microsoft.LobServices.OracleDB/2007/03)
        public virtual void Notification(Notification request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

WCF サービス モデルを使用したデータベース変更通知の受信

このセクションでは、Oracle Database アダプターを使用してクエリ通知を受信する .NET アプリケーションを記述する方法について説明します。

クエリ通知を受信するには

  1. アダプター サービス参照の追加プラグインを使用して、ACCOUNTACTIVITY テーブルに対する選択操作用の WCF クライアントを生成します。 このクライアントを使用して、通知メッセージを受信した後に選択操作を実行します。 プロジェクトに新しいクラス TableOperation.cs を追加し、次のコードスニペットを追加して Select 操作を実行します。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Notification_ServiceModel
    {
        class TableOperation
        {
            public void TableOp()
            {
                //////////////////////////////////////////////////////////////////////
                // CREATING THE CLIENT AND SETTING CLIENT CREDENTIALS
                //////////////////////////////////////////////////////////////////////
    
                SCOTT_Table_ACCOUNTACTIVITYClient client = new SCOTT_Table_ACCOUNTACTIVITYClient("OracleDBBinding_SCOTT_Table_ACCOUNTACTIVITY");
                client.ClientCredentials.UserName.UserName = "SCOTT";
                client.ClientCredentials.UserName.Password = "TIGER";
    
                ////////////////////////////////////////////////////////////////////
                // OPENING THE CLIENT
                //////////////////////////////////////////////////////////////////////
                try
                {
                    Console.WriteLine("Opening the client ...");
                    client.Open();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                ////////////////////////////////////////////////////////////////////////////////////////
                // SELECTING THE LAST INSERTED VALUE
                ////////////////////////////////////////////////////////////////////////////////////////
    
                Console.WriteLine("The application will now select the last inserted record");
    
                microsoft.lobservices.oracledb._2007._03.SCOTT.Table.ACCOUNTACTIVITY.ACCOUNTACTIVITYRECORDSELECT[] selectRecords;
    
                try
                {
                    selectRecords = client.Select("*", "WHERE PROCESSED = 'n'");
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                Console.WriteLine("The details of the newly added records are:");
                Console.WriteLine("********************************************");
                for (int i = 0; i < selectRecords.Length; i++)
                {
                    Console.WriteLine("Transaction ID   : " + selectRecords[i].TID);
                    Console.WriteLine("Account ID       : " + selectRecords[i].ACCOUNT);
                    Console.WriteLine("Processed Status : " + selectRecords[i].PROCESSED);
                    Console.WriteLine();
                }
                Console.WriteLine("********************************************");
            }
        }
    }
    
    
  2. アダプター サービス参照の追加プラグインを使用して、 通知 操作の WCF サービス コントラクト (インターフェイス) とヘルパー クラスを生成します。

    詳細については、「 Oracle Database ソリューション成果物の WCF クライアントまたは WCF サービス コントラクトを生成する」を参照してください。 必要に応じて、サービス コントラクトとヘルパー クラスの生成中にバインディング プロパティを指定できます。 これにより、生成された構成ファイルに正しく設定されます。

  3. 手順 2 で生成されたインターフェイスとヘルパー クラスから WCF サービスを実装します。 このクラスの Notification メソッドは、 Notification 操作から受信したデータの処理でエラーが発生した場合に、例外をスローして操作を中止できます。それ以外の場合、メソッドは何も返しません。 WCF サービス クラスの属性を次に示す必要があります。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Notification メソッド内では、アプリケーション ロジックを直接実装できます。 このクラスは、OracleDBBindingService.csにあります。 この例のこのコードは、 OracleDBBindingService クラスを サブクラス化します。 このコードでは、受信した通知メッセージがコンソールに書き込まれます。 さらに、Select 操作を実行するために、TableOperation クラス内の TableOp メソッドが呼び出されます。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
        public class NotificationService : OracleDBBindingNamespace.OracleDBBindingService
        {
            public override void Notification(Notification request)
            {
                Console.WriteLine("\nNew Notification Received");
                Console.WriteLine("*************************************************");
                Console.WriteLine(request.Info);
                Console.WriteLine(request.Source);
                Console.WriteLine(request.Type);
                Console.WriteLine("*************************************************");
    
                TableOperation Ops = new TableOperation();
                Ops.TableOp();
    
            }
        }
    
  4. Oracle データベースの資格情報を渡すには、次のクラスを実装する必要があります。 アプリケーションの後半では、このクラスをインスタンス化して資格情報を渡します。

    class NotificationCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }
    
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }
    
        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new NotificationCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  5. OracleDBBinding を作成し、バインディング プロパティを指定してクエリ通知を受信するようにアダプターを構成します。 これは、コードで明示的に行うか、構成で宣言によって行うことができます。 少なくとも、 InboundOperationType および NotificationStatement バインディング プロパティを指定する必要があります。

    OracleDBBinding binding = new OracleDBBinding();
    binding.InboundOperationType = InboundOperation.Notification;
    binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'";
    binding.NotifyOnListenerStart = true;
    binding.NotificationPort = 10;
    

    Von Bedeutung

    NotificationPort バインド プロパティの値は、Windows ファイアウォールの例外リストに追加する必要があるのと同じポート番号に設定する必要があります。 Windows ファイアウォールの例外リストにポートを追加する方法については、 https://go.microsoft.com/fwlink/?LinkId=196959を参照してください。

    Von Bedeutung

    NotificationPort バインド プロパティを設定しない場合、アダプターは、このバインディング プロパティの既定値の -1 を想定します。 このような場合は、通知メッセージを受信するために Windows ファイアウォールを完全に無効にする必要があります。

  6. 手順 4 で作成 した NotificationCredentials クラスをインスタンス化して、Oracle データベースの資格情報を指定します。

    NotificationCredentials credentials = new NotificationCredentials();
    credentials.UserName.UserName = "SCOTT";
    credentials.UserName.Password = "TIGER";
    
  7. 手順 3 で作成した WCF サービスのインスタンスを作成します。

    // create service instance
    NotificationService service = new NotificationService();
    
  8. WCF サービスとベース接続 URI を使用して 、System.ServiceModel.ServiceHost のインスタンスを作成します。 ここで資格情報も指定する必要があります。

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("oracledb://adapter") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  9. サービス ホストにサービス エンドポイントを追加します。 これを行うには:

    • 手順 5 で作成したバインディングを使用します。

    • 資格情報を含む接続 URI と、必要に応じて受信 ID を指定します。

    • コントラクトを "Notification_OperationGroup" として指定します。

      // Add service endpoint: be sure to specify Notification_OperationGroup as the contract
      Uri ConnectionUri = new Uri("oracledb://adapter");
      serviceHost.AddServiceEndpoint("Notification_OperationGroup", binding, ConnectionUri);
      
  10. 通知メッセージを受信するには、サービス ホストを開きます。

    // Open the service host to begin receiving notifications
    serviceHost.Open();
    
  11. 通知の受信を停止するには、サービス ホストを閉じます。

    serviceHost.Close();
    

次の例は、ACCOUNTACTIVITY テーブルの通知メッセージを受信する .NET アプリケーションを示しています。

次のコード スニペットは 、TableOperation.cs クラスをインスタンス化し、 TableOp メソッドを呼び出します。 クラスとメソッドについては、手順 1 で説明します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Adapters.OracleDB;
using Microsoft.ServiceModel.Channels;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;

namespace Notification_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class NotificationService : OracleDBBindingNamespace.OracleDBBindingService
    {
        public override void Notification(Notification request)
        {
            Console.WriteLine("\nNew Notification Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine(request.Info);
            Console.WriteLine(request.Source);
            Console.WriteLine(request.Type);
            Console.WriteLine("*************************************************");

            TableOperation Ops = new TableOperation();
            Ops.TableOp();

        }
    }

    class NotificationCredentials : ClientCredentials, IServiceBehavior
    {
        public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
        {
            bindingParameters.Add(this);
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        { }

        protected override ClientCredentials CloneCore()
        {
            ClientCredentials clone = new NotificationCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost serviceHost = null;
            try
            {
                Console.WriteLine("Sample started...");
                Console.WriteLine("Press any key to start receiving notifications...");
                Console.ReadLine();

                OracleDBBinding binding = new OracleDBBinding();
                binding.InboundOperationType = InboundOperation.Notification;
                binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'";
                binding.NotifyOnListenerStart = true;
                binding.NotificationPort = 10;

                // This URI is used to specify the address for the ServiceEndpoint
                // It must contain the InboundId that was used to generate
                // the WCF service callback interface
                Uri ConnectionUri = new Uri("oracledb://adapter");

                // This URI is used to initialize the ServiceHost. It cannot contain
                // an InboundID; otherwise,an exception is thrown when
                // the ServiceHost is initialized.
                Uri[] baseUri = new Uri[] { new Uri("oracledb://adapter") };

                NotificationCredentials credentials = new NotificationCredentials();
                credentials.UserName.UserName = "SCOTT";
                credentials.UserName.Password = "TIGER";

                Console.WriteLine("Opening service host...");
                NotificationService service = new NotificationService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("Notification_OperationGroup", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Waiting for notification...");

                Console.WriteLine("\nHit <RETURN> to stop receiving notification");
                Console.ReadLine();
            }
            catch (Exception e)
            {
                Console.WriteLine("Exception :" + e.Message);
                Console.ReadLine();

                /* If there is an error it will be specified in the inner exception */
                if (e.InnerException != null)
                {
                    Console.WriteLine("InnerException: " + e.InnerException.Message);
                    Console.ReadLine();
                }
            }
            finally
            {
                // IMPORTANT: you must close the ServiceHost to stop polling
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }

        }
    }
}

こちらもご覧ください

WCF サービス モデルを使用して Oracle データベース アプリケーションを開発する