WCF サービス モデルを使用して SQL からクエリ通知を受信する

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

Note

ユーザー定義型の列を持つテーブルに対して操作を実行する場合は、アプリケーションの開発を開始する前 に、「SQL アダプターを使用して、ユーザー定義型のテーブルとビューに対する操作」 を参照してください。

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

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

Binding プロパティ 説明
InboundOperationType 実行する受信操作を指定します。 通知メッセージを受信するには、これを [通知] に設定します。
NotificationStatement クエリ通知の登録に使用する SQL ステートメント (SELECT または EXEC <ストアド プロシージャ>) を指定します。 アダプターは、指定した SQL ステートメントの結果セットが変更された場合にのみ、SQL Serverから通知メッセージを取得します。
NotifyOnListenerStart リスナーの起動時にアダプターがアダプター クライアントに通知を送信するかどうかを指定します。

これらのプロパティの詳細については、「BizTalk Adapter for SQL Server アダプター バインド プロパティ」を参照してください。 SQL アダプターを使用してSQL Serverから通知を受信する方法の詳細については、詳細を参照してください。

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

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

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

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

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

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

このトピックで使用される例について

このトピックの例では、Employee テーブルの通知を受け取ります。 テーブルを生成するスクリプトは、サンプルと共に提供されます。 サンプルの詳細については、「 SQL アダプターのサンプル」を参照してください。 このトピックに基づくサンプル Notification_ServiceModelは、SQL アダプターのサンプルでも提供されています。

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

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

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

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

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/", ConfigurationName="NotificationOperation")]
public interface NotificationOperation {

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/Notification/) of message
    // Notification does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="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://schemas.microsoft.com/Sql/2008/05/Notification/", IsWrapped=true)]
public partial class Notification {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=0)]
    public string Info;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=1)]
    public string Source;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/Notification/", Order=2)]
    public string Type;

    public Notification() {
    }

    public Notification(string Info, string Source, string Type) {
        this.Info = Info;
        this.Source = Source;
        this.Type = Type;
    }
}

WCF サービス クラス

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

namespace SqlAdapterBindingNamespace {

    public class SqlAdapterBindingService : NotificationOperation {

        // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/Notification/)
        // of message Notification does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
        public virtual void Notification(Notification request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

WCF サービス モデルを使用したクエリ通知の受信

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

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

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

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Notification_ServiceModel
    {
        public class TableOperation
        {
            public void TableOp()
            {
                ///////////////////////////////////////////////////////////////////////
                // CREATING THE CLIENT
                ///////////////////////////////////////////////////////////////////////
    
                TableOp_dbo_EmployeeClient client = new TableOp_dbo_EmployeeClient("SqlAdapterBinding_TableOp_dbo_Employee");
    
                client.ClientCredentials.UserName.UserName = "<Enter user name here>";
                client.ClientCredentials.UserName.Password = "<Enter password here>";
    
                ///////////////////////////////////////////////////////////////////////
                // OPENING THE CLIENT
                ///////////////////////////////////////////////////////////////////////
    
                try
                {
                    Console.WriteLine("Opening Client...");
                    client.Open();
                }
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                ///////////////////////////////////////////////////////////////////////
                // SELECTING THE LAST INSERTED RECORD FROM THE TABLE
                ///////////////////////////////////////////////////////////////////////
                schemas.microsoft.com.Sql._2008._05.Types.Tables.dbo.Employee[] selectRecords;
    
                try
                {
                    selectRecords = client.Select("*", "where Status=0");
                }
    
                catch (Exception ex)
                {
                    Console.WriteLine("Exception: " + ex.Message);
                    throw;
                }
    
                Console.WriteLine("The details of the newly added employee are:");
                Console.WriteLine("********************************************");
                for (int i = 0; i < selectRecords.Length; i++)
                {
                    Console.WriteLine("Employee Name      : " + selectRecords[i].Name);
                    Console.WriteLine("Employee Designation: " + selectRecords[i].Designation);
                    Console.WriteLine("Employee Status    : " + selectRecords[i].Status);
                    Console.WriteLine();
                }
                Console.WriteLine("********************************************");
    
    

    重要

    このコード スニペットは、Point UDT 列を含む Employee テーブルに対して操作を実行するため、アプリケーションの実行中に、プロジェクトの \bin\Debug フォルダーの下に UDT DLL を配置してください。

  2. アダプター サービス参照の追加プラグインを使用して、 通知 操作用の WCF サービス コントラクト (インターフェイス) とヘルパー クラスを生成します。

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

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

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

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

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class NotificationService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        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("*************************************************");
    
            // Invoke th TableOp method in the TableOperation class
            TableOperation Ops = new TableOperation();
            Ops.TableOp();
        }
    }
    
  4. SQL アダプターは接続 URI の一部として資格情報を受け入れないので、SQL Server データベースの資格情報を渡すには、次のクラスを実装する必要があります。 アプリケーションの後者の部分では、このクラスをインスタンス化して、SQL Server資格情報を渡します。

    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. SqlAdapterBinding を作成し、バインド プロパティを指定してクエリ通知を受信するようにアダプターを構成します。 これは、コードで明示的に行うか、構成で宣言によって行うことができます。 少なくとも、 InboundOperationType および NotificationStatement バインド プロパティを指定する必要があります。

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.Notification;
    binding.NotificationStatement = "SELECT Employee_ID, Name FROM dbo.Employee WHERE Status=0";
    binding.NotifyOnListenerStart = true;
    
  6. 手順 4 で作成SQL Server NotificationCredentials クラスをインスタンス化して、データベース資格情報を指定します。

    NotificationCredentials credentials = new NotificationCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  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("mssql://mysqlserver//mydatabase") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  9. サービス エンドポイントをサービス ホストに追加します。 これを行うには、次の手順を実行します。

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

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

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

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

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

    serviceHost.Close();
    

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

Note

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

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Microsoft.Adapters.Sql;
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 : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        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
            {
                SqlAdapterBinding binding = new SqlAdapterBinding();
                binding.InboundOperationType = InboundOperation.Notification;
                binding.NotificationStatement = "SELECT Employee_ID, Name FROM dbo.Employee WHERE Status=0";
                binding.NotifyOnListenerStart = true;

                // This URI is used to specify the address for the ServiceEndpoint
                // It must contain the InboundId (if any) that was used to generate
                // the WCF service callback interface
                Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?");

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

                NotificationCredentials credentials = new NotificationCredentials();
                credentials.UserName.UserName = "<Enter user name here>";
                credentials.UserName.Password = "<Enter password here>";

                Console.WriteLine("Opening service host...");
                NotificationService service = new NotificationService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("NotificationOperation", 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 receiving notifications
                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close();
                else
                    serviceHost.Abort();
            }
        }
    }
}

参照

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