使用 SELECT 語句搭配 WCF 通道模型輪詢 Oracle E-Business Suite
您可以設定 Oracle E-Business 配接器,以使用 SELECT 語句持續輪詢 Oracle E-Business Suite 中的介面資料表、介面檢視、資料表和檢視,以接收週期性資料變更訊息。 您可以將 SELECT 語句指定為配接器定期執行的輪詢語句,以輪詢 Oracle E-Business Suite。 您也可以指定配接器在執行輪詢語句之後執行的輪詢後 PL/SQL 程式碼區塊。
若要啟用輪詢,您必須指定本主題中所述的特定系結屬性。 如需配接器如何支援輪詢的詳細資訊,請參閱 支援使用輪詢的輸入呼叫。
使用 Oracle E-Business Suite 配接器系結屬性設定輪詢作業
下表摘要說明您用來設定配接器以接收資料變更訊息的 Oracle E-Business 配接器系結屬性。 在執行輪詢應用程式時,您必須指定這些系結屬性。
Binding 屬性 | Description |
---|---|
InboundOperationType | 指定您要執行 輪詢 或 通知 輸入作業。 預設值為 Polling。 |
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 腳本來執行此動作。 執行此腳本之後,下一個輪詢作業會擷取插入資料表的新記錄。
使用輪詢要求訊息
配接器會在您的程式碼上叫用輪詢作業,以輪詢 Oracle E-Business Suite。 也就是說,配接器會傳送您透過 IInputChannel 通道圖形收到的輪詢要求訊息。 輪詢要求訊息包含 PollingInput 系結屬性所指定的查詢結果集。 您可以使用下列兩種方式之一來取用輪詢訊息:
若要使用節點值串流來取用訊息,您必須在回應訊息上呼叫 WriteBodyContents 方法,並將實作節點值串流的 XmlDictionaryWriter 傳遞給它。
若要使用節點串流來取用訊息,您可以在回應訊息上呼叫 GetReaderAtBodyContents 以取得 XmlReader。
關於本主題中使用的範例
本主題中的範例會輪詢 MS_SAMPLE_EMPLOYEE 介面資料表。 產生資料表的腳本會隨附範例。 如需範例的詳細資訊,請參閱 Oracle EBS 配接器的範例。 Oracle E-Business 配接器範例也會提供以本主題為基礎的範例 SelectPolling_ChannelModel。
使用 WCF 通道模型接收輪詢作業的輸入訊息
本節提供有關如何撰寫 .NET 應用程式 (通道模型) ,以使用 Oracle E-Business 配接器接收輸入輪詢訊息的指示。
從配接器接收輪詢訊息
在 Visual Studio 中建立 Microsoft Visual C# ® 專案。 針對本主題,建立主控台應用程式。
在方案總管中,新增 、
Microsoft.ServiceModel.Channels
System.ServiceModel
和 的System.Runtime.Serialization
參考Microsoft.Adapters.OracleEBS
。開啟 Program.cs 檔案,並新增下列命名空間:
Microsoft.Adapters.OracleEBS
System.ServiceModel
System.ServiceModel.Description
System.ServiceModel.Channels
System.Xml
指定連線 URI。 如需配接器連線 URI 的詳細資訊,請參閱 建立 Oracle E-Business Suite 連線 URI。
Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name");
建立 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 = "<Enter user name here>"; binding.OraclePassword = "<Enter password here>"; binding.OracleEBSResponsibilityName = "<Enter responsibility here>";
建立系結參數集合並設定認證。
ClientCredentials credentials = new ClientCredentials(); credentials.UserName.UserName = "<Enter user name here>"; credentials.UserName.Password = "<Enter password here>"; BindingParameterCollection bindingParams = new BindingParameterCollection(); bindingParams.Add(credentials);
建立通道接聽程式並加以開啟。 您可以叫用OracleEBSBinding上的BuildChannelListener < IInputChannel >方法來建立接聽程式。
IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams); listener.Open();
叫用接聽程式上的AcceptChannel方法並開啟它,以取得IInputChannel通道。
IInputChannel channel = listener.AcceptChannel(); channel.Open();
在通道上叫用 接收 ,以從配接器取得下一個輸入訊息。
Message message = channel.Receive();
取用輸入作業傳回的結果集。 您可以使用 XmlReader 或 XmlDictionaryWriter來取用訊息。
XmlReader reader = message.GetReaderAtBodyContents();
當您完成處理要求時,請關閉通道。
channel.Close()
重要
完成處理輸入作業之後,您必須關閉通道。 無法關閉通道可能會影響程式碼的行為。
當您完成接收資料變更的訊息時,請關閉接聽程式。
listener.Close()
重要
關閉接聽程式並不會關閉使用接聽程式建立的通道。 您必須明確關閉使用接聽程式建立的每個通道。
範例
下列範例顯示輪詢應用程式,其會輪詢MS_SAMPLE_EMPLOYEE介面資料表。 PollingInput屬性包含 select 語句,可讀取MS_SAMPLE_EMPLOYEE資料表中的所有資料,而 post poll 語句會刪除相同資料表中的所有資料。 輪詢訊息會寫入 C:\PollingOutput.xml
。
後續輪詢訊息將不會包含任何記錄,直到將資料新增至MS_SAMPLE_EMPLOYEE介面資料表為止。 您可以執行範例所提供的 insert_apps_data.sql 腳本來執行此動作。 執行此腳本之後,下一個輪詢作業會擷取插入資料表的新記錄。 配接器會繼續輪詢,直到您按下 < RETURN > 關閉服務主機為止。
using System;
using Microsoft.Adapters.OracleEBS;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Xml;
namespace SelectPolling_ChannelModel
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Sample started. This sample will poll 5 times and will perform the following tasks:");
Console.WriteLine("Press any key to start polling...");
Console.ReadLine();
IChannelListener<IInputChannel> listener = null;
IInputChannel channel = null;
try
{
TimeSpan messageTimeout = new TimeSpan(0, 0, 30);
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 = "<Enter user name here>";
binding.OraclePassword = "<Enter password here>";
binding.OracleEBSResponsibilityName = "<Enter responsibility here>";
Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name?");
ClientCredentials credentials = new ClientCredentials();
credentials.UserName.UserName = "<Enter user name here>";
credentials.UserName.Password = "<Enter password here>";
BindingParameterCollection bindingParams = new BindingParameterCollection();
bindingParams.Add(credentials);
listener = binding.BuildChannelListener<IInputChannel>(ConnectionUri, bindingParams);
listener.Open();
channel = listener.AcceptChannel();
channel.Open();
Console.WriteLine("Channel and Listener opened...");
Console.WriteLine("\nWaiting for polled data...");
Console.WriteLine("Receive request timeout is {0}", messageTimeout);
// Poll five times with the specified message timeout
// If a timeout occurs polling will be aborted
for (int i = 0; i < 5; i++)
{
Console.WriteLine("Polling: " + i);
Message message = null;
XmlReader reader = null;
try
{
//Message is received so process the results
message = channel.Receive(messageTimeout);
}
catch (System.TimeoutException toEx)
{
Console.WriteLine("\nNo data for request number {0}: {1}", i + 1, toEx.Message);
continue;
}
// Get the query results using an XML reader
try
{
reader = message.GetReaderAtBodyContents();
}
catch (Exception ex)
{
Console.WriteLine("Exception :" + ex);
throw;
}
XmlDocument doc = new XmlDocument();
doc.Load(reader);
using (XmlWriter writer = XmlWriter.Create("C:\\PollingOutput.xml"))
{
doc.WriteTo(writer);
Console.WriteLine("The polling response is saved at 'C:\\PollingOutput.xml'");
}
// return the cursor
Console.WriteLine();
// close the reader
reader.Close();
message.Close();
}
Console.WriteLine("\nPolling done -- hit <RETURN> to finish");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine("Exception is: " + ex.Message);
Console.ReadLine();
if (ex.InnerException != null)
{
Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);
Console.ReadLine();
}
}
finally
{
// IMPORTANT: close the channel and listener to stop polling
if (channel != null)
{
if (channel.State == CommunicationState.Opened)
channel.Close();
else
channel.Abort();
}
if (listener != null)
{
if (listener.State == CommunicationState.Opened)
listener.Close();
else
listener.Abort();
}
}
}
}
}