共用方式為


使用 WCF 服務模型從 SQL 接收查詢通知

本主題示範如何設定 SQL 配接器,以接收來自SQL Server資料庫的查詢通知訊息。 若要示範通知,請考慮具有 [狀態] 資料行的資料表 Employee。 當新記錄插入此資料表時,Status 資料行的值會設定為 0。 您可以使用 SQL 語句來擷取 Status 資料行為 「0」 的所有記錄,藉此設定配接器以接收通知。 您可以藉由指定 NotificationStatement 系結屬性的 SQL 語句來執行此動作。 配接器用戶端收到通知之後,它可以包含邏輯,以在SQL Server資料庫上執行任何後續工作。 在此範例中,為了簡單起見,配接器用戶端會將 [狀態] 資料行列為 「0」 資料表中的所有記錄。

注意

如果您要對具有使用者定義型別資料行的資料表執行作業,請務必先使用 SQL 配接器主題來參考 具有使用者定義型別之資料表和檢視的作業 ,然後再開始開發應用程式。

使用 SQL 配接器系結屬性設定通知

下表摘要說明您用來設定從SQL Server接收通知的 SQL 配接器系結屬性。 您必須在執行 .NET 應用程式時指定這些系結屬性,才能從SQL Server資料庫接收通知。

Binding 屬性 Description
InboundOperationType 指定您想要執行的輸入作業。 若要接收通知訊息,請將此設定為 [通知]。
NotificationStatement 指定用來註冊查詢通知的 SQL 語句 (SELECT 或 EXEC <預存程式>) 。 只有在指定 SQL 語句的結果集變更時,配接器才會從SQL Server取得通知訊息。
NotifyOnListenerStart 指定當接聽程式啟動時,配接器是否傳送通知給配接器用戶端。

如需這些屬性的更完整描述,請參閱閱讀 BizTalk Adapter for SQL Server 配接器系結屬性。 如需如何使用 SQL 配接器接收SQL Server通知的完整描述,請參閱進一步。

使用 WCF 服務模型設定通知

若要使用 WCF 服務模型接收通知,您必須:

  1. 從配接器所公開的中繼資料產生 WCF 服務合約 (介面) 。 若要這樣做,您可以使用新增配接器服務參考外掛程式。

  2. 為 [員工] 資料表上的 [選取 ] 作業產生 WCF 用戶端。 若要這樣做,您可以使用新增配接器服務參考外掛程式。

  3. 從這個介面實作 WCF 服務。

  4. 使用服務主機裝載此 WCF 服務, (System.ServiceModel.ServiceHost) 。

關於本主題中使用的範例

本主題中的範例會收到 Employee 資料表的通知。 產生資料表的腳本會隨附範例。 如需範例的詳細資訊,請參閱 SQL 配接器的範例。 SQL 配接器範例也會提供以本主題為基礎的範例 Notification_ServiceModel

WCF 服務合約和類別

您可以使用 [新增配接器服務參考外掛程式] 來建立 WCF 服務合約 (介面) 和支援 通知 作業的類別。 如需產生 WCF 服務合約的詳細資訊,請參閱為SQL Server成品產生 WCF 用戶端或 WCF 服務合約

WCF 服務合約 (介面)

下列程式碼顯示針對 通知 作業產生的 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 服務模型接收查詢通知

本節提供如何撰寫 .NET 應用程式以使用 SQL 配接器接收查詢通知的指示。

接收查詢通知

  1. 使用 [新增配接器服務參考外掛程式],在Employee資料表上產生選取作業的WCF 用戶端。 您將使用此用戶端在收到通知訊息之後執行 Select 作業。 將新的類別 TableOperation.cs 新增至專案,並新增下列程式碼片段來執行選取作業。

    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 資料表上執行作業,因此在執行應用程式時,請務必將 UDT DLL 放在專案的 \bin\Debug 資料夾下。

  2. 使用 [新增配接器服務參考外掛程式] 來產生 WCF 服務合約, (通知作業的 介面) 和協助程式類別。

    如需詳細資訊,請參閱為SQL Server成品產生 WCF 用戶端或 WCF 服務合約。 您可以在產生服務合約和協助程式類別時選擇性地指定系結屬性。 這可確保它們已正確設定在產生的組態檔中。

  3. 從步驟 2 中產生的介面和協助程式類別實作 WCF 服務。 如果發生錯誤處理從通知作業收到的資料,這個類別的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 ,並藉由指定系結屬性來設定配接器以接收查詢通知。 您可以在程式碼中明確執行此動作,或在組態中以宣告方式執行此動作。 您至少必須指定 InboundOperationTypeNotificationStatement 系結屬性。

    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 中建立的NotificationCredentials類別,指定SQL Server資料庫認證。

    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 中建立的系結。

    • 指定包含認證的連線 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();
    

範例

下列範例顯示 .NET 應用程式,可接收 Employee 資料表的通知訊息。

注意

下列程式碼片段會具現化 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 應用程式