共用方式為


使用 WCF 服務模型從SQL Server接收強型輪詢型資料變更訊息

您可以將 SQL 配接器設定為接收來自SQL Server的強型別輪詢訊息。 您可以指定配接器執行的輪詢語句來輪詢資料庫。 輪詢語句可以是 SELECT 語句或傳回結果集的預存程式。 您必須在想要接收強型別結果集的案例中使用強型別輪詢。 如需配接器如何支援強型別輪詢的詳細資訊,請參閱 支援使用輪詢的輸入呼叫

重要

如果您想要在單一應用程式中有多個輪詢作業,您必須在連線 URI 中指定 InboundID 連線屬性,使其成為唯一的一部分。 您指定的輸入識別碼會新增至作業命名空間,使其成為唯一的。

本主題示範輪詢的方式

在本主題中,若要示範 SQL 配接器如何支援接收強型別的資料變更訊息,請建立 .NET 應用程式並產生 TypedPolling 作業的 WCF 服務合約。 產生 WCF 服務合約時,請務必指定下列專案:

  • 您必須將 InboundID 指定為連線 URI 的一部分。

  • 您必須為 PollingStatement 系結屬性指定輪詢語句。

    此外,如果您想要在產生 Proxy 類別時指定其他輪詢相關系結屬性,請將 PolledDataAvailableStatement 指定為:

SELECT COUNT(*) FROM Employee

PolledDataAvailableStatement必須傳回結果集,其中包含正值的第一個儲存格。 如果第一個儲存格不包含正值,配接器就不會執行輪詢語句。

在輪詢語句中,執行下列作業:

  1. 從 Employee 資料表中選取所有資料列。

  2. 執行預存程式 (MOVE_EMP_DATA) 將所有記錄從 Employee 資料表移至 EmployeeHistory 資料表。

  3. 執行預存程式 (ADD_EMP_DETAILS) ,將新記錄新增至 Employee 資料表。 此程式會採用員工名稱、指定和薪資作為參數。

    若要執行這些作業,您必須為 PollingStatement 系結屬性指定下列專案,同時產生 WCF 服務合約和協助程式類別:

SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000

執行輪詢語句之後,會選取 Employee 資料表中的所有記錄,並收到來自SQL Server的訊息。 配接器執行MOVE_EMP_DATA預存程式之後,所有記錄都會移至 EmployeeHistory 資料表。 然後,會執行ADD_EMP_DETAILS預存程式,將新記錄新增至 Employee 資料表。 下一個輪詢執行只會傳回單一記錄。 此週期會繼續執行,直到您關閉服務主機為止。

使用 SQL 配接器系結屬性設定具型別輪詢

下表摘要說明您用來設定配接器以接收資料變更訊息的 SQL 配接器系結屬性。 除了 PollingStatement 系結屬性以外,執行 .NET 應用程式時,需要本節中所列的所有其他系結屬性。 您必須先指定 PollingStatement 系結屬性,才能產生 WCF 服務合約 TypedPolling 作業。

Binding 屬性 Description
InboundOperationType 指定您要執行 PollingTypedPollingNotification 輸入作業。 預設值為 Polling。 若要接收強型別輪詢訊息,請將此設定為 TypedPolling
PolledDataAvailableStatement 指定配接器執行的 SQL 語句,以判斷是否有任何資料可供輪詢。 SQL 語句必須傳回包含資料列和資料行的結果集。 只有在資料列可用時,才會執行 針對 PollingStatement 系結屬性指定的 SQL 語句。
PollingIntervalInSeconds 指定間隔,以秒為單位,SQL 配接器會執行 針對 PolledDataAvailableStatement 系結屬性指定的語句。 預設值為 30 秒。 輪詢間隔會決定連續輪詢之間的時間間隔。 如果語句是在指定的間隔內執行,配接器會等候間隔中的剩餘時間。
PollingStatement 指定要輪詢SQL Server資料庫資料表的 SQL 語句。 您可以指定輪詢語句的簡單 SELECT 語句或預存程式。 預設值是 null。 您必須指定 PollingStatement 的值,才能啟用輪詢。 只有在有資料可供輪詢時,才會執行輪詢語句,這是由 PolledDataAvailableStatement 系結屬性所決定。 您可以指定以分號分隔的任意數目 SQL 語句。 重要: 針對 TypedPolling,您必須先指定這個系結屬性,才能產生中繼資料。
PollWhileDataFound 指定 SQL 配接器是否忽略輪詢間隔,並持續執行 針對 PolledDataAvailableStatement 系結屬性指定的 SQL 語句,如果正在輪詢的資料表中有資料可用。 如果資料表中沒有可用的資料,配接器會還原為在指定的輪詢間隔執行 SQL 語句。 預設值為 false

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

在 WCF 服務模型中設定強型別輪詢

若要在使用 WCF 服務模型時接收 輪詢 作業,您必須:

  1. 從配接器所公開的中繼資料,為 TypedPolling 作業產生 WCF 服務合約 (介面) 。 若要這樣做,您可以使用新增配接器服務參考 Visual Studio 外掛程式。 產生此範例的 WCF 服務合約時,請確定:

    • 您可以將 InboundID 指定為 Employee

    • 您可以指定 PollingStatement 系結屬性的輪詢語句。 在此範例中,請將輪詢語句指定為:

      SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000
      
  2. 從這個介面實作 WCF 服務。

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

關於本主題中使用的範例

本主題中的範例會輪詢 Employee 資料表。 此範例也會使用 MOVE_EMP_DATA 和 ADD_EMP_DETAILS 預存程式。 產生這些成品的腳本會隨附範例。 如需範例的詳細資訊,請參閱 SQL 配接器的範例。 SQL 配接器範例也會提供以本主題為基礎的範例 TypedPolling_ServiceModel

WCF 服務合約和類別

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

WCF 服務合約 (介面)

下列程式碼顯示針對 TypedPolling 作業產生的 WCF 服務合約 (介面) 。

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

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee) of message TypedPolling
    // does not match the default value (https://schemas.microsoft.com/Sql/2008/05/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="TypedPolling")]
    void TypedPolling(TypedPolling request);
}

訊息合約

如果指定,訊息合約命名空間會由連線 URI 中的 InboundID 參數修改。 在此範例中,您已將輸入識別碼指定為 Employee。 要求訊息會傳回強型別的結果集。

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="TypedPolling", WrapperNamespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", IsWrapped=true)]
public partial class TypedPolling {

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=0)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0;

[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/Sql/2008/05/TypedPolling/Employee", Order=1)]
    public schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1;

    public TypedPolling() {
    }

    public TypedPolling(schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet0[] TypedPollingResultSet0, schemas.microsoft.com.Sql._2008._05.TypedPolling.Employee.TypedPollingResultSet1[] TypedPollingResultSet1) {
        this.TypedPollingResultSet0 = TypedPollingResultSet0;
        this.TypedPollingResultSet1 = TypedPollingResultSet1;
    }
}

WCF 服務類別

[新增配接器服務參考外掛程式] 也會產生檔案,該檔案具有從服務合約 (介面) 實作之 WCF 服務類別的存根。 檔案名為 SqlAdapterBindingService.cs。 您可以將邏輯直接插入此類別來處理 TypedPolling 作業。 下列程式碼顯示新增配接器服務參考外掛程式所產生的 WCF 服務類別。

namespace SqlAdapterBindingNamespace {

    public class SqlAdapterBindingService : TypedPolling_Employee {

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

接收輪詢作業的強型別輸入訊息

本節提供有關如何撰寫 .NET 應用程式的指示,以使用 SQL 配接器接收強型別的輸入輪詢訊息。

  1. 使用 [新增配接器服務參考外掛程式] 來產生 WCF 服務合約 (介面) 和 TypedPolling 作業的協助程式類別。 請確定您在產生此範例的 WCF 服務合約時指定下列專案:

    • 您必須將 InboundID 指定為 Employee

    • 您必須為 PollingStatement 系結屬性指定輪詢語句。 在此範例中,請將輪詢語句指定為:

      SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000
      

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

  2. 從步驟 1 中產生的介面和協助程式類別實作 WCF 服務。 如果遇到錯誤處理從 TypedPolling作業收到的資料,這個類別的TypedPolling方法可能會擲回例外狀況以中止輪詢交易;否則方法不會傳回任何專案。 您必須屬性 WCF 服務類別,如下所示:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    TypedPolling 方法中,您可以直接實作應用程式邏輯。 您可以在 SqlAdapterBindingService.cs 中找到此類別。 此範例子類別中的這個程式碼是 SqlAdapterBindingService 類別。 在此程式碼中,接收為強型別結果集的輪詢訊息會寫入主控台。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");
    
            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }
    
  3. 因為 SQL 配接器不接受認證作為連線 URI 的一部分,所以您必須實作下列類別來傳遞SQL Server資料庫的認證。 在應用程式的後半部,您會具現化此類別,以傳遞SQL Server認證。

    class PollingCredentials : 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 PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  4. 建立 SqlAdapterBinding ,並藉由指定系結屬性來設定輪詢作業。 您可以在程式碼中明確執行此動作,或在組態中以宣告方式執行此動作。 您至少必須指定 InboundOperationTypePolledDataAvailableStatementPollingStatement

    SqlAdapterBinding binding = new SqlAdapterBinding();
    binding.InboundOperationType = InboundOperation.TypedPolling;
    binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
    binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
    
  5. 藉由具現化您在步驟 3 中建立的PollingCredentials類別,指定SQL Server資料庫認證。

    PollingCredentials credentials = new PollingCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  6. 建立在步驟 2 中建立之 WCF 服務的實例。

    // create service instance
    PollingService service = new PollingService();
    
  7. 使用 WCF 服務和基底連線 URI 建立 System.ServiceModel.ServiceHost 的實例。 基底連線 URI 不能包含輸入識別碼。 您也必須在這裡指定認證。

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("mssql://mysqlserver//mydatabase") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  8. 將服務端點新增至服務主機。 作法如下:

    • 使用步驟 4 中建立的系結。

    • 指定包含認證的連線 URI,並視需要指定輸入識別碼。

    • 將合約指定為 「TypedPolling_Employee」。

    // Add service endpoint: be sure to specify TypedPolling_Employee as the contract
    Uri ConnectionUri = new Uri("mssql://mysqlserver//mydatabase?InboundID=Employee");
    serviceHost.AddServiceEndpoint("TypedPolling_Employee", binding, ConnectionUri);
    
  9. 若要接收輪詢資料,請開啟服務主機。 每當查詢傳回結果集時,配接器就會傳回資料。

    // Open the service host to begin polling
    serviceHost.Open();
    
  10. 若要終止輪詢,請關閉服務主機。

    重要

    配接器會繼續輪詢,直到服務主機關閉為止。

    serviceHost.Close();
    

範例

下列範例顯示執行 Employee 資料表的輪詢查詢。 輪詢語句會執行下列工作:

  1. 從 Employee 資料表中選取所有記錄。

  2. 執行MOVE_EMP_DATA預存程式,將所有記錄從 Employee 資料表移至 EmployeeHistory 資料表。

  3. 執行ADD_EMP_DETAILS預存程式,將單一記錄新增至 Employee 資料表。

    第一個輪詢訊息會包含 Employee 資料表中的所有記錄。 後續輪詢訊息只會包含ADD_EMP_DETAILS預存程式所插入的最後一筆記錄。 配接器會繼續輪詢,直到您按下 <RETURN> 關閉服務主機為止。

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 TypedPolling_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class PollingService : SqlAdapterBindingNamespace.SqlAdapterBindingService
    {
        public override void TypedPolling(TypedPolling request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Employee ID\tName\tDesignation\tSalary");

            for (int i = 0; i < request.TypedPollingResultSet0.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.TypedPollingResultSet0[i].Employee_ID,
                request.TypedPollingResultSet0[i].Name,
                request.TypedPollingResultSet0[i].Designation,
                request.TypedPollingResultSet0[i].Salary);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }

    class PollingCredentials : 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 PollingCredentials();
            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 polling...");
                Console.ReadLine();

                SqlAdapterBinding binding = new SqlAdapterBinding();
                binding.InboundOperationType = InboundOperation.TypedPolling;
                binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM EMPLOYEE";
                binding.PollingStatement = "SELECT * FROM Employee;EXEC MOVE_EMP_DATA;EXEC ADD_EMP_DETAILS John, Tester, 100000";
                Console.WriteLine("Binding properties assigned...");

                // 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("mssql://mysqlserver//mydatabase?InboundId=Employee");

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

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

                Console.WriteLine("Opening service host...");
                PollingService service = new PollingService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("TypedPolling_Employee", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Polling started...");
                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();
            }
        }
    }
}

另請參閱

使用 SQL 配接器搭配 WCF 服務模型輪詢SQL Server