共用方式為


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

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

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

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

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

Binding 屬性 Description
InboundOperationType 指定您要執行 輪詢通知 輸入作業。 預設值為 Polling
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 配接器的範例。 Oracle E-Business 配接器範例也會提供以本主題為基礎的範例 StoredProcPolling_ServiceModel

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.");
        }
    }
}

使用預存程式接收用於輪詢的輸入訊息

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

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

  1. 使用 [新增配接器服務參考外掛程式] 來產生 WCF 服務合約, (介面) 和 GET_ACTIVITYS 輸入作業的協助程式類別。 如需詳細資訊,請參閱 產生 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 資料表中的所有記錄。 後續輪詢訊息不會包含任何記錄,因為 post poll 語句會刪除記錄。 在將更多資料新增至 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