您可以使用 SELECT 語句持續輪詢 Oracle E-Business Suite 中的介面數據表、介面檢視、數據表和檢視,來設定 Oracle E-Business 配接器來接收定期的數據變更訊息。 您可以將 SELECT 語句指定為輪詢語句,配接器會定期執行以輪詢 Oracle E-Business Suite。 您也可以指定輪詢語句執行後,配接器要執行的 PL/SQL 程式代碼區塊。
若要啟用輪詢,您必須指定特定系結屬性,如本主題所述。 如需配接器如何支援輪詢的詳細資訊,請參閱 使用輪詢支援輸入呼叫。
使用 Oracle E-Business Suite 配接器繫結屬性設定輪詢操作
下表摘要說明您用來設定配接器以接收數據變更訊息的 Oracle E-Business 配接器系結屬性。 在執行輪詢應用程式時,您必須指定這些系結屬性。
| 綁定屬性 | 說明 |
|---|---|
| InboundOperationType | 指定您要執行 輪詢 或 通知 輸入作業。 預設為 輪詢。 |
| PolledDataAvailableStatement | 指定配接器執行的 SQL 語句,以判斷是否有任何數據可供輪詢。 只有當記錄可用時,您為 PollingInput 系結屬性指定的 SELECT 語句才會執行。 |
| PollingInterval | 指定 Oracle E-Business 配接器執行 PolledDataAvailableStatement 系結屬性所指定的語句的間隔,以秒為單位。 預設值為30秒。 輪詢間隔會決定連續輪詢之間的時間間隔。 如果語句在指定的間隔內執行,適配器會在間隔的剩餘時間內暫停。 |
| PollingInput | 指定輪詢語句。 若要使用 SELECT 陳述式查詢評估,您必須為此綁定屬性指定一個 SELECT 陳述式。 預設值為 null。 您必須指定 PollingInput 系結屬性的值,才能啟用輪詢。 只有在有數據可供輪詢時,才會執行輪詢語句,這是 由 PolledDataAvailableStatement 系結 屬性所決定。 |
| PollingAction | 指定輪詢作業的動作。 您可以使用「新增轉接器服務參考」Visual Studio 外掛程式,從為操作生成的服務接口中判斷輪詢動作。 |
| PostPollStatement | 指定執行 PollingInput 系結屬性所指定語句之後執行的語句區塊。 |
| PollWhileDataFound | 如果數據表中有可用的數據,指定 Oracle E-Business 配接器是否應忽略輪詢間隔並持續執行輪詢語句。 如果數據表中沒有可用的數據,配接器會還原為在指定的輪詢間隔執行輪詢語句。 預設值為 false。 |
如需更完整的這些屬性描述,請參閱 BizTalk Adapter for Oracle E-Business Suite 綁定屬性。 如需如何使用 Oracle E-Business 配接器來輪詢 Oracle 資料庫的詳細說明,請繼續閱讀。
本主題如何展示輪詢的運作方式
在本主題中,為了示範 Oracle E-Business 配接器如何使用 SELECT 語句支援接收數據變更訊息,您可以在 Application Object Library 應用程式中輪詢MS_SAMPLE_EMPLOYEE介面數據表。 當您執行隨附範例的create_apps_artifacts.sql腳本,以在 Oracle E-Business Suite 中建立這些物件時,就會建立此數據表。
為了示範輪詢作業,我們會執行下列動作:
為 PolledDataAvailableStatement 系結 屬性指定 SELECT 語句,以判斷要輪詢的介面數據表 (MS_SAMPLE_EMPLOYEE) 具有任何數據的位置。 在此範例中,您可以將這個系結屬性設定為:
SELECT COUNT (*) FROM MS_SAMPLE_EMPLOYEE這可確保配接器只有在 MS_SAMPLE_EMPLOYEE 介面數據表有資料時,才會執行輪詢語句。
指定 PollingInput 系結屬性的 SELECT 語句。 此語句會擷取MS_SAMPLE_EMPLOYEE介面數據表中的所有數據列。 在此範例中,您可以將這個系結屬性設定為:
SELECT * FROM MS_SAMPLE_EMPLOYEE FOR UPDATE備註
如需 SELECT 語句中使用的 FOR UPDATE 子句相關信息,請參閱 從 Oracle E-Business Suite 接收輪詢型數據變更訊息。
指定 DELETE 語句做為 PostPollStatement 系結 屬性的一部分。 此語句會刪除介面數據表MS_SAMPLE_EMPLOYEE中的所有數據。 在此範例中,您可以將這個系結屬性設定為:
DELETE FROM MS_SAMPLE_EMPLOYEE發生這種情況之後,下次執行針對 PollingInput 指定的語句時,它將不會擷取任何數據。
在將更多數據新增至MS_SAMPLE_EMPLOYEE介面數據表之前,您不會收到任何輪詢訊息,因此您必須使用新的記錄重新填入MS_SAMPLE_EMPLOYEE介面數據表。 您可以執行範例所提供的insert_apps_data.sql腳本來執行此動作。 執行這個腳本後,下一次輪詢作業將擷取插入到資料表中的新記錄。
在 WCF 服務模型中設定輪詢
若要使用 Oracle E-Business 配接器搭配 WCF 服務模型來輪詢介面表,您必須:
針對MS_SAMPLE_EMPLOYEE介面數據表上的 輪詢 作業產生 WCF 服務合約(介面)。 若要這樣做,您可以使用 [新增配接器服務參考外掛程式]。
從這個介面實作 WCF 服務。
使用服務主機裝載此 WCF 服務(System.ServiceModel.ServiceHost)。
關於本主題中使用的範例
本主題中的範例會輪詢MS_SAMPLE_EMPLOYEE介面數據表。 產生數據表的腳本會隨附範例。 如需範例的詳細資訊,請參閱 Oracle EBS 配接器的範例。 提供了這個主題所涵蓋的範例 SelectPolling_ServiceModel,此範例也隨附在 Oracle E-Business 配接器範例中。
WCF 服務合約和類別
您可以使用新增配接器服務參考外掛程式來建立 WCF 服務合約(介面)和支援 輪詢 作業的類別。 如需產生 WCF 服務合約的詳細資訊,請參閱 產生 WCF 用戶端或 Oracle E-Business Suite 解決方案成品的 WCF 服務合約。
WCF 服務合約 (介面)
下列程式代碼顯示針對 MS_SAMPLE_EMPLOYEE 介面數據表上 輪詢 作業所產生的 WCF 服務合約(interface)。
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/", ConfigurationName="InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE")]
public interface InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE_EMPLOYEE) of message Poll
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="InterfaceTables/Poll/FND/APPS/MS_SAMPLE_EMPLOYEE")]
void Poll(Poll request);
}
訊息合約
以下是在 MS_SAMPLE_EMPLOYEE 介面資料表上進行 輪詢 作業之訊息合約。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Poll", WrapperNamespace="http://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE" +
"_EMPLOYEE", IsWrapped=true)]
public partial class Poll {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE" +
"_EMPLOYEE", Order=0)]
public schemas.microsoft.com.OracleEBS._2008._05.TableViewRecord.APPS.MS_SAMPLE_EMPLOYEE.SelectRecord[] DATA;
public Poll() {
}
public Poll(schemas.microsoft.com.OracleEBS._2008._05.TableViewRecord.APPS.MS_SAMPLE_EMPLOYEE.SelectRecord[] DATA) {
this.DATA = DATA;
}
}
WCF 服務類別
[新增配接器服務參考外掛程式] 也會產生一個檔案,其中包含根據服務合約 (介面) 所建立的 WCF 服務類別的存根。 檔名OracleEBSBindingService.cs。 您可以將處理輪詢作業的邏輯直接插入至這個類別。 下列程式代碼顯示新增配接器服務參考外掛程式所產生的 WCF 服務類別。
namespace OracleEBSBindingNamespace {
public class OracleEBSBindingService : InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE_EMPLOYEE) of message Poll
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
public virtual void Poll(Poll request) {
throw new System.NotImplementedException("The method or operation is not implemented.");
}
}
}
使用 SELECT 語句接收輪詢作業的輸入訊息
本節提供如何使用 Oracle E-Business 配接器撰寫 .NET 應用程式以接收輸入輪詢訊息的指示。
使用 SELECT 語句接收輪詢訊息
使用 [新增配接器服務參考外掛程式] 來產生 MS_SAMPLE_EMPLOYEE 介面資料表上 輪詢 作業的 WCF 服務契約(介面)和輔助類別。 如需詳細資訊,請參閱 產生 ORACLE E-Business Suite 解決方案成品的 WCF 用戶端或 WCF 服務合約。 您可以選擇性地指定繫結屬性,在產生服務合約和輔助類別時。 這可確保它們已正確設定在產生的組態檔中。
從步驟 1 所產生的介面和協助程式類別實作 WCF 服務。 如果在處理從 輪詢 操作所接收到的數據時遇到錯誤,這個類別的 Poll 方法可能會拋出例外以中止該輪詢交易;否則,該方法不會傳回任何內容。 請按照以下方式設定 WCF 服務類別的屬性:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]在 Poll 方法內,您可以直接實作應用程式邏輯。 您可以在 OracleEBSBindingService.cs中找到這個類別。 此範例中的這個程式代碼子類別是 OracleEBSBindingService 類別。 在這段程式碼中,輪詢訊息被接收後寫入到主控台。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService { public override void Poll(Poll request) { Console.WriteLine("\nNew Polling Records Received"); Console.WriteLine("*************************************************"); Console.WriteLine("Emp No\tName\tDesignation\tSalary"); for (int i = 0; i < request.DATA.Length; i++) { Console.WriteLine("{0}\t{1}\t{2}\t{3}", request.DATA[i].EMP_NO, request.DATA[i].NAME, request.DATA[i].DESIGNATION, request.DATA[i].SALARY); } 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 MS_SAMPLE_EMPLOYEE"; binding.PollingInput = "SELECT * FROM MS_SAMPLE_EMPLOYEE FOR UPDATE"; binding.PollingAction = "InterfaceTables/Poll/FND/APPS/MS_SAMPLE_EMPLOYEE"; binding.PostPollStatement = "DELETE FROM MS_SAMPLE_EMPLOYEE";因為您要輪詢介面資料表,因此您也必須設定應用程式環境。 如需設定應用程式內容所需的應用程式內容和系結屬性的詳細資訊,請參閱 設定應用程式內容。
binding.OracleUserName = "myOracleEBSUserName"; binding.OraclePassword = "myOracleEBSPassword"; binding.OracleEBSResponsibilityName = "myOracleEBSResponsibility";藉由具現化您在步驟 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,並視需要指定輸入識別碼。
將合約指定為「InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE」,以查詢MS_SAMPLE_EMPLOYEE介面數據表。
// Add service endpoint: be sure to specify InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE as the contract Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name"); serviceHost.AddServiceEndpoint("InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE", binding, ConnectionUri);
若要接收輪詢數據,請開啟服務主機。 每當查詢傳回結果集時,配接器就會傳回數據。
// Open the service host to begin polling serviceHost.Open();若要終止輪詢,請關閉服務主機。
這很重要
轉接器會繼續輪詢,直到服務主機關閉為止。
serviceHost.Close();
範例
下列範例顯示一個輪詢應用程式,其會對MS_SAMPLE_EMPLOYEE介面表進行輪詢。
PollingInput 屬性包含 select 語句,可讀取MS_SAMPLE_EMPLOYEE數據表中的所有數據,而 post poll 語句會刪除相同數據表中的所有數據。 第一個輪詢訊息會提供來自 MS_SAMPLE_EMPLOYEE 介面數據表的所有記錄。 後續輪詢訊息將不會包含任何記錄,因為postpoll語句會刪除記錄。 在將更多數據新增至MS_SAMPLE_EMPLOYEE介面數據表之前,您不會收到任何輪詢訊息。 因此,您必須使用新的記錄重新填入MS_SAMPLE_EMPLOYEE介面數據表。 您可以執行範例所提供的insert_apps_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 SelectPolling_ServiceModel
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
{
public override void Poll(Poll request)
{
Console.WriteLine("\nNew Polling Records Received");
Console.WriteLine("*************************************************");
Console.WriteLine("Emp No\tName\tDesignation\tSalary");
for (int i = 0; i < request.DATA.Length; i++)
{
Console.WriteLine("{0}\t{1}\t{2}\t{3}",
request.DATA[i].EMP_NO,
request.DATA[i].NAME,
request.DATA[i].DESIGNATION,
request.DATA[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();
OracleEBSBinding binding = new OracleEBSBinding();
binding.InboundOperationType = InboundOperation.Polling;
binding.PolledDataAvailableStatement = "SELECT COUNT (*) FROM MS_SAMPLE_EMPLOYEE";
binding.PollingInput = "SELECT * FROM MS_SAMPLE_EMPLOYEE FOR UPDATE";
binding.PollingAction = "InterfaceTables/Poll/FND/APPS/MS_SAMPLE_EMPLOYEE";
binding.PostPollStatement = "DELETE FROM MS_SAMPLE_EMPLOYEE";
binding.OracleUserName = "myOracleEBSUserName";
binding.OraclePassword = "myOracleEBSPassword";
binding.OracleEBSResponsibilityName = "myOracleEBSResponsibility";
// 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("InterfaceTables_FND_APPS_MS_SAMPLE_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();
}
}
}
}