共用方式為


使用預存程式搭配 WCF 服務模型輪詢 Oracle E-Business Suite

您可以使用預存程式定期輪詢 Oracle 資料庫,將 Oracle E-Business 配接器設定為接收定期數據變更訊息。 您可以將預存程式指定為輪詢語句,配接器會定期執行以輪詢 Oracle 資料庫。

若要啟用輪詢,您必須指定特定系結屬性,如本主題所述。 如需配接器如何支援輪詢的詳細資訊,請參閱 使用輪詢支援輸入呼叫

使用 Oracle E-Business 配接器系結屬性配置輪詢作業

下表摘要說明您用來設定配接器以接收數據變更訊息的 Oracle E-Business 配接器系結屬性。 在執行輪詢應用程式時,您必須指定這些系結屬性。

綁定屬性 說明
InboundOperationType 指定您要執行 輪詢式通知式 的輸入作業。 預設為 輪詢
PolledDataAvailableStatement 指定配接器執行的 SQL 語句,以判斷是否有任何數據可供輪詢。 只有當記錄可用時,您為 PollingInput 系結屬性指定的預存程式才會執行。
PollingInterval 指定 Oracle E-Business 配接器執行 PolledDataAvailableStatement 系結屬性所指定的語句的間隔,以秒為單位。 預設值為30秒。 輪詢間隔會決定連續輪詢之間的時間間隔。 如果語句在指定的間隔內執行,適配器會在間隔的剩餘時間內暫停。
PollingInput 指定輪詢語句。 若要使用預存程序進行輪詢,您必須指定此繫結屬性的完整請求訊息。 要求訊息必須與您傳送至配接器相同,才能將預存程式叫用為輸出作業。 預設值為 null。

您必須指定 PollingInput 系結屬性的值,才能啟用輪詢。 只有在有數據可供輪詢時,才會執行輪詢語句,這是 由 PolledDataAvailableStatement 系結 屬性所決定。
PollingAction 指定輪詢作業的動作。 您可以使用「新增轉接器服務參考」Visual Studio 外掛程式,從為操作生成的服務接口中判斷輪詢動作。
PostPollStatement 指定執行 PollingInput 系結屬性所指定語句之後執行的語句區塊。
PollWhileDataFound 如果數據表中有可用的數據,指定 Oracle E-Business 配接器是否應忽略輪詢間隔並持續執行輪詢語句。 如果數據表中沒有可用的數據,配接器會還原為在指定的輪詢間隔執行輪詢語句。 預設值為 false。

如需更完整的這些屬性描述,請參閱 BizTalk Adapter for Oracle E-Business Suite 綁定屬性。 如需如何使用 Oracle E-Business 配接器進行輪詢的完整描述,請閱讀下列各節。

本主題如何展示輪詢的運作方式

在本主題中,為了示範 Oracle E-Business 配接器如何支援使用預存程式接收數據變更訊息,您可以使用 GET_ACTIVITYS 預存程式來輪詢 Oracle 資料庫中的 ACCOUNTACTIVITY 數據表。 此預存程式可搭配 ACCOUNT_PKG 套件使用。 您可以執行範例所提供的 SQL 腳本,以在資料庫中建立這些物件。

備註

本主題中的範例會查詢 ACCOUNTACTIVITY 資料表,它是一個由範例所提供的腳本建立的基底資料庫表。 您必須執行本主題中所述的類似程式,才能輪詢任何其他數據表,包括介面數據表。

為了示範輪詢作業,我們會執行下列動作:

  • PolledDataAvailableStatement 系結 屬性指定 SELECT 語句,以判斷要輪詢的數據表 (ACCOUNTACTIVITY) 具有任何數據的位置。 在此範例中,您可以將這個系結屬性設定為:

    SELECT COUNT (*) FROM ACCOUNTACTIVITY
    

    這可確保只有在 ACCOUNTACTIVITY 數據表有一些記錄時,配接器才會執行輪詢語句。

  • 藉由提供要求訊息做為 PollingInput 系結屬性的一部分,執行預存程式GET_ACTIVITYS。 這個預存程式會擷取 ACCOUNTACTIVITY 資料表中的所有數據列,而且您會從配接器取得回應消息。

  • PostPollStatement 系結 屬性中執行 PL/SQL 區塊。 此語句會將所有數據從 ACCOUNTACTIVITY 資料表移至資料庫中的另一個數據表。 發生這種情況之後,下次執行 PollingInput 時,它將不會擷取任何數據,因此GET_ACTIVITYS預存程式會傳回空的回應消息。

  • 在將更多數據新增至 ACCOUNTACTIVITY 資料表之前,您仍會繼續取得空的回應消息,因此您必須使用新的記錄重新填入 ACCOUNTACTIVITY 數據表。 您可以執行範例所提供的more_activity_data.sql腳本來執行此動作。 執行這個腳本後,下一次輪詢作業將擷取插入到資料表中的新記錄。

在 WCF 服務模型中設定輪詢

若要使用預存程式搭配 Oracle E-Business 配接器與 WCF 服務模型進行輪詢,您必須:

  • 為要輪詢的預存程式產生 WCF 服務合約(介面)。 在此範例中,您必須為 GET_ACTIVITYS 預存程式產生 WCF 服務合約做為輸入作業。 若要這樣做,您可以使用 [新增配接器服務參考外掛程式]。

  • 從這個介面實作 WCF 服務。

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

關於本主題中使用的範例

本主題中的範例會使用 GET_ACTIVITYS 預存程式輪詢 ACCOUNTACTIVITY 資料庫數據表。 產生數據表和預存程式的腳本會隨附範例。 如需範例的詳細資訊,請參閱 Oracle EBS 配接器的範例。 本主題所依據的範例 StoredProcPolling_ServiceModel也隨附 Oracle E-Business 配接器範例。

WCF 服務合約和類別

您可以使用 [新增配接器服務參考外掛程式] 來建立 WCF 服務合約(介面)和支援 GET_ACTIVITYS 輸入作業的類別。 如需產生 WCF 服務合約的詳細資訊,請參閱 產生 WCF 用戶端或 Oracle E-Business Suite 解決方案成品的 WCF 服務合約

WCF 服務合約 (介面)

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

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

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

訊息合約

以下是 GET_ACTIVITYS 入站操作的訊息合約。

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="GET_ACTIVITYS", WrapperNamespace="http://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PK" +
    "G", IsWrapped=true)]
public partial class GET_ACTIVITYS {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/PollingPackageApis/APPS/ACCOUNT_PK" +
        "G", Order=0)]
    public schemas.microsoft.com.OracleEBS._2008._05.RecordTypes.APPS.ACCOUNT_PKG.GET_ACTIVITYS.OUTRECSRecord[] OUTRECS;

    public GET_ACTIVITYS() {
    }

    public GET_ACTIVITYS(schemas.microsoft.com.OracleEBS._2008._05.RecordTypes.APPS.ACCOUNT_PKG.GET_ACTIVITYS.OUTRECSRecord[] OUTRECS) {
        this.OUTRECS = OUTRECS;
    }
}

WCF 服務類別

[新增配接器服務參考外掛程式] 也會產生一個檔案,其中包含根據服務合約 (介面) 所建立的 WCF 服務類別的存根。 檔名OracleEBSBindingService.cs。 您可以將程式邏輯直接插入此類別中以處理 GET_ACTIVITYS 作業。 下列程式代碼顯示新增配接器服務參考外掛程式所產生的 WCF 服務類別。

namespace OracleEBSBindingNamespace {

    public class OracleEBSBindingService : PollingPackageApis_APPS_ACCOUNT_PKG {

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

使用預存程式接收用於輪詢操作的傳入訊息

本節提供如何使用 Oracle E-Business 配接器撰寫 .NET 應用程式以接收輸入輪詢訊息的指示。

使用預存程式接收輪詢訊息

  1. 使用 [新增配接器服務參考外掛程式] 來產生 GET_ACTIVITYS 內部作業的 WCF 服務合約(介面)和輔助類別。 如需詳細資訊,請參閱 產生 ORACLE E-Business Suite 解決方案成品的 WCF 用戶端或 WCF 服務合約。 您可以選擇性地指定繫結屬性,在產生服務合約和輔助類別時。 這可確保它們已正確設定在產生的組態檔中。

  2. 從步驟 1 所產生的介面和協助程式類別實作 WCF 服務。 如果遇到錯誤處理從GET_ACTIVITYS作業收到的數據,此類別的GET_ACTIVITYS方法可能會擲回例外狀況來中止輪詢交易;否則方法不會傳回任何內容。 請按照以下方式設定 WCF 服務類別的屬性:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    GET_ACTIVITYS 方法內,您可以直接實作應用程式邏輯。 您可以在 OracleEBSBindingService.cs中找到這個類別。 此範例中的這個程式代碼子類別是 OracleEBSBindingService 類別。 在這段程式碼中,輪詢訊息被接收後寫入到主控台。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
    {
        public override void  GET_ACTIVITYS(GET_ACTIVITYS request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Tx Id\tAccount\tAmount\tProcessed");
            for (int i = 0; i < request.OUTRECS.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.OUTRECS[i].TID,
                request.OUTRECS[i].ACCOUNT,
                request.OUTRECS[i].AMOUNT,
                request.OUTRECS[i].PROCESSED);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }
    
  3. 您必須實作下列類別,以避免在 URI 中傳遞認證。 在應用程式的後一個部分中,您將具現化此類別以傳遞認證。

    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. 建立 OracleEBSBinding ,並藉由指定系結屬性來設定輪詢作業。 您可以在程式代碼中明確執行此動作,或在組態中以宣告方式執行此動作。 您至少必須指定 InboundOperationTypePolledDataAvailableStatementPollingInputPollingAction 系結屬性。

    OracleEBSBinding binding = new OracleEBSBinding();
    binding.InboundOperationType = InboundOperation.Polling;
    binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM ACCOUNTACTIVITY";
    binding.PollingInput = "<GET_ACTIVITYS xmlns='http://schemas.microsoft.com/OracleEBS/2008/05/PackageApis/APPS/ACCOUNT_PKG'><INRECS>OPEN ? FOR SELECT * FROM ACCOUNTACTIVITY</INRECS></GET_ACTIVITYS>";
    binding.PollingAction = "PollingPackageApis/APPS/ACCOUNT_PKG/GET_ACTIVITYS";
    binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";
    

    備註

    請注意, PollingInput 系結屬性的值包含叫用 GET_ACTIVITYS 預存程式做為輸出作業的要求訊息。

    這很重要

    在此範例中,因為您要輪詢資料庫資料表,因此不需要設置應用程式的執行環境。 不過,如果您要輪詢介面數據表,您必須指定 OracleUserNameOraclePasswordOracleEBSResponsibilityName 系結屬性來設定應用程式內容。 如需應用程式內容的詳細資訊,請參閱 設定應用程式內容

  5. 藉由具現化您在步驟 3 中建立的 PollingCredentials 類別,以指定 Oracle E-Business Suite 認證。

    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("oracleebs://ebs_instance_name") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  8. 將服務端點新增至服務主機。 要達成此目的:

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

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

    • 將合約指定為 「PollingPackageApis_APPS_ACCOUNT_PKG」,以輪詢MS_SAMPLE_EMPLOYEE介面數據表。

    // Add service endpoint: be sure to specify PollingPackageApis_APPS_ACCOUNT_PKG as the contract
    Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name");
    serviceHost.AddServiceEndpoint("PollingPackageApis_APPS_ACCOUNT_PKG", binding, ConnectionUri);
    
  9. 若要接收輪詢數據,請開啟服務主機。 每當查詢傳回結果集時,配接器就會傳回數據。

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

    這很重要

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

    serviceHost.Close();
    

範例

下列範例顯示輪詢應用程式,該應用程式會使用 GET_ACTIVITYS 預存程式輪詢 ACCOUNTACTIVITY 資料庫數據表。 PollingInput 系結屬性包含叫用GET_ACTIVITYS預存程式的要求訊息,該預存程式會從 ACCOUNTACTIVITY 數據表讀取所有數據,而 post poll 語句會將所有數據從 ACCOUNTACTIVITY 移至 ACTIVITYHISTORY 數據表。

第一個輪詢訊息會提供 ACCOUNTACTIVITY 數據表中的所有記錄。 後續輪詢訊息將不會包含任何記錄,因為postpoll語句會刪除記錄。 在將更多數據新增至 ACCOUNTACTIVITY 數據表之前,您不會收到任何輪詢訊息,因此您必須使用新的記錄重新填入 ACCOUNTACTIVITY 數據表。 您可以執行範例所提供的more_activity_data.sql腳本來執行此動作。

執行這個腳本後,下一次輪詢作業將擷取插入到資料表中的新記錄。 配接器會繼續輪詢,直到您按下 <RETURN>關閉服務主機為止。

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

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

    public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
    {
        public override void  GET_ACTIVITYS(GET_ACTIVITYS request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Tx Id\tAccount\tAmount\tProcessed");
            for (int i = 0; i < request.OUTRECS.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.OUTRECS[i].TID,
                request.OUTRECS[i].ACCOUNT,
                request.OUTRECS[i].AMOUNT,
                request.OUTRECS[i].PROCESSED);
            }
            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();

                OracleEBSBinding binding = new OracleEBSBinding();
                binding.InboundOperationType = InboundOperation.Polling;
                binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM ACCOUNTACTIVITY";
                binding.PollingInput = "<GET_ACTIVITYS xmlns='http://schemas.microsoft.com/OracleEBS/2008/05/PackageApis/APPS/ACCOUNT_PKG'><INRECS>OPEN ? FOR SELECT * FROM ACCOUNTACTIVITY</INRECS></GET_ACTIVITYS>";
                binding.PollingAction = "PollingPackageApis/APPS/ACCOUNT_PKG/GET_ACTIVITYS";
                binding.PostPollStatement = "BEGIN ACCOUNT_PKG.PROCESS_ACTIVITY(); END;";

                // 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("oracleebs://ebs_instance_name");

                // 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("oracleebs://ebs_instance_name") };

                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("PollingPackageApis_APPS_ACCOUNT_PKG", 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();
            }
        }
    }
}

另請參閱

透過 WCF 服務模型輪詢 Oracle E-Business Suite