使用預存程式搭配 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 配接器接收輸入輪詢訊息的指示。
使用預存程式接收輪詢訊息
使用 [新增配接器服務參考外掛程式] 來產生 WCF 服務合約, (介面) 和 GET_ACTIVITYS 輸入作業的協助程式類別。 如需詳細資訊,請參閱 產生 Oracle E-Business Suite 解決方案成品的 WCF 用戶端或 WCF 服務合約。 您可以在產生服務合約和協助程式類別時選擇性地指定系結屬性。 這可確保它們已正確設定在產生的組態檔中。
從步驟 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"); } }
您必須實作下列類別,以避免將認證傳遞為 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; } }
建立 OracleEBSBinding ,並藉由指定系結屬性來設定輪詢作業。 您可以在程式碼中明確執行此動作,或在組態中以宣告方式執行此動作。 您至少必須指定 InboundOperationType、 PolledDataAvailableStatement、 PollingInput和 PollingAction 系結屬性。
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 預存程式叫用為輸出作業的要求訊息。
重要
在此範例中,因為您正在輪詢資料庫資料表,所以不需要設定應用程式內容。 不過,如果您要輪詢介面資料表,則必須藉由指定 OracleUserName、 OraclePassword和 OracleEBSResponsibilityName 系結屬性來設定應用程式內容。 如需應用程式內容的詳細資訊,請參閱 設定應用程式內容。
藉由具現化您在步驟 3 中建立的 PollingCredentials 類別,指定 Oracle E-Business Suite 認證。
PollingCredentials credentials = new PollingCredentials(); credentials.UserName.UserName = "<Enter user name here>"; credentials.UserName.Password = "<Enter password here>";
建立在步驟 2 中建立之 WCF 服務的實例。
// create service instance PollingService service = new PollingService();
使用 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);
將服務端點新增至服務主機。 作法如下:
使用步驟 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);
若要接收輪詢資料,請開啟服務主機。 每當查詢傳回結果集時,配接器就會傳回資料。
// Open the service host to begin polling serviceHost.Open();
若要終止輪詢,請關閉服務主機。
重要
配接器會繼續輪詢,直到服務主機關閉為止。
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();
}
}
}
}