本主題示範如何設定 Oracle E-Business 配接器,以接收來自 Oracle 資料庫的查詢通知訊息。 若要示範通知,請考慮一個名為 ACCOUNTACTIVITY 的資料表,其中有一個「已處理」欄。 將新記錄插入此數據表時,Status 資料行的值會設定為 「n」。。 您可以使用 SQL 語句來註冊通知,以設定配接器以接收通知,以擷取具有 「Processed」 資料行的所有記錄為 「n」。 您可以指定 NotificationStatement 系結 屬性的 SQL 語句來執行此動作。 配接器用戶端收到通知之後,它可以包含邏輯,在 Oracle 資料庫上執行任何後續工作。 在此範例中,為了簡化,轉接器客戶端會列出資料表中所有「Processed」欄位為「n」的記錄。
使用 Oracle E-Business 配接器系結屬性設定通知
下表摘要說明您用來設定從 Oracle E-Business Suite 接收通知的 Oracle E-Business 配接器系結屬性。 您必須在執行 .NET 應用程式時指定這些系結屬性,才能接收通知。
| 綁定屬性 | 說明 |
|---|---|
| InboundOperationType | 指定您要執行的輸入作業。 若要接收通知訊息,請將此設定為 [通知]。 |
| NotificationPort | 指定 ODP.NET 必須開啟的埠號碼,以接聽 Oracle 資料庫中的資料庫變更通知。 |
| NotificationStatement | 指定用來註冊查詢通知的 Select 語句。 只有在指定 Select 語句的結果集變更時,配接器才會取得通知訊息。 |
| NotifyOnListenerStart | 指定當接聽程序啟動時,配接器是否傳送通知給配接器用戶端。 |
如需更完整的這些屬性描述,請參閱 BizTalk Adapter for Oracle E-Business Suite 綁定屬性。 如需如何使用 Oracle E-Business 配接器從 Oracle E-Business Suite 接收通知的完整描述,請閱讀本主題的其餘部分。
使用 WCF 服務模型設定通知
若要使用 WCF 服務模型接收通知,您必須:
從配接器所公開的元數據產生 通知 作業的 WCF 服務合約(介面)。 若要這樣做,您可以使用 [新增配接器服務參考外掛程式]。
在 ACCOUNTACTIVITY 數據表上產生 Select 作業的 WCF 用戶端。 若要這樣做,您可以使用 [新增配接器服務參考外掛程式]。
從這個介面實作 WCF 服務。
使用服務主機裝載此 WCF 服務(System.ServiceModel.ServiceHost)。
關於本主題中使用的範例
本主題中的範例接收來自 ACCOUNTACTIVITY 資料表的通知。 產生數據表的腳本會隨附範例。 如需範例的詳細資訊,請參閱 Oracle EBS 配接器的範例。 基於本主題的範例 Notification_ServiceModel,也隨 Oracle E-Business 配接器範例提供。
WCF 服務合約和類別
您可以使用新增配接器服務參考外掛程式來建立 WCF 服務合約(介面)和支援 通知 作業的類別。 如需產生 WCF 服務合約的詳細資訊,請參閱 產生 WCF 用戶端或 Oracle E-Business Suite 解決方案成品的 WCF 服務合約。
WCF 服務合約 (介面)
下列程式代碼顯示針對 通知 作業產生的 WCF 服務合約(介面)。
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/", ConfigurationName="Notification_")]
public interface Notification_ {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/Notification/) of message Notification
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
[System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="Notification")]
void Notification(Notification request);
}
訊息合約
以下是通知作業的訊息合約。
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Notification", WrapperNamespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", IsWrapped=true)]
public partial class Notification {
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", Order=0)]
public schemas.microsoft.com.OracleEBS._2008._05.Notification.NotificationDetails[] Details;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", Order=1)]
public string Info;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", Order=2)]
public string[] ResourceNames;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", Order=3)]
public string Source;
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/Notification/", Order=4)]
public string Type;
public Notification() {
}
public Notification(schemas.microsoft.com.OracleEBS._2008._05.Notification.NotificationDetails[] Details, string Info, string[] ResourceNames, string Source, string Type) {
this.Details = Details;
this.Info = Info;
this.ResourceNames = ResourceNames;
this.Source = Source;
this.Type = Type;
}
}
WCF 服務類別
[新增配接器服務參考外掛程式] 也會產生一個檔案,其中包含根據服務合約 (介面) 所建立的 WCF 服務類別的存根。 檔名OracleEBSBindingService.cs。 您可以將處理 通知 作業的邏輯直接插入到此類別中。 下列程式代碼顯示新增配接器服務參考外掛程式所產生的 WCF 服務類別。
namespace OracleEBSBindingNamespace {
public class OracleEBSBindingService : Notification_ {
// CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/Notification/) of message Notification
// does not match the default value (https://schemas.microsoft.com/OracleEBS/)
public virtual void Notification(Notification request) {
throw new System.NotImplementedException("The method or operation is not implemented.");
}
}
}
使用 WCF 服務模型接收查詢通知
本節提供如何使用 Oracle E-Business 配接器撰寫 .NET 應用程式以接收查詢通知的指示。
接收查詢通知
使用 [新增配接器服務參考外掛程式],在 ACCOUNTACTIVITY 數據表上產生 SELECT 作業的 WCF 用戶端。 您將使用此用戶端在收到通知訊息之後執行 Select 作業。 將新的類別TableOperation.cs新增至您的專案,並新增下列代碼段來執行 Select 作業。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Notification_ServiceModel { class TableOperation { public void TableOp() { ////////////////////////////////////////////////////////////////////// // CREATING THE CLIENT AND SETTING CLIENT CREDENTIALS ////////////////////////////////////////////////////////////////////// Tables_APPS_ACCOUNTACTIVITYClient client = new Tables_APPS_ACCOUNTACTIVITYClient(); client.ClientCredentials.UserName.UserName = "<Enter user name here>"; client.ClientCredentials.UserName.Password = "<Enter password here>"; //////////////////////////////////////////////////////////////////// // OPENING THE CLIENT ////////////////////////////////////////////////////////////////////// try { Console.WriteLine("Opening the client ..."); client.Open(); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); throw; } //////////////////////////////////////////////////////////////////////////////////////// // SELECTING THE LAST INSERTED VALUES //////////////////////////////////////////////////////////////////////////////////////// Console.WriteLine("The application will now select the last inserted record"); schemas.microsoft.com.OracleEBS._2008._05.TableViewRecord.APPS.ACCOUNTACTIVITY.SelectRecord[] selectRecords; try { selectRecords = client.Select("*", "WHERE PROCESSED = 'n'"); } catch (Exception ex) { Console.WriteLine("Exception: " + ex.Message); throw; } Console.WriteLine("The details of the newly added records are:"); Console.WriteLine("********************************************"); for (int i = 0; i < selectRecords.Length; i++) { Console.WriteLine("Transaction ID : " + selectRecords[i].TID); Console.WriteLine("Account ID : " + selectRecords[i].ACCOUNT); Console.WriteLine("Processed Status : " + selectRecords[i].PROCESSED); Console.WriteLine(); } Console.WriteLine("********************************************"); } } }使用 [新增配接器服務參考外掛程式] 來產生 通知 作業的 WCF 服務合約(介面)和協助程序類別。
如需詳細資訊,請參閱 產生 ORACLE E-Business Suite 解決方案成品的 WCF 用戶端或 WCF 服務合約。 您可以選擇性地指定繫結屬性,在產生服務合約和輔助類別時。 這可確保它們已正確設定在產生的組態檔中。
從步驟 2 中產生的介面和協助程式類別實作 WCF 服務。 如果發生錯誤處理從通知作業收到的數據,這個類別的 Notification 方法可能會擲回例外狀況來中止作業;否則方法不會傳回任何專案。 請按照以下方式設定 WCF 服務類別的屬性:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]在 Notification 方法內,您可以直接實作應用程式邏輯。 您可以在 OracleEBSBindingService.cs中找到這個類別。 此範例中的這個程式代碼子類別是 OracleEBSBindingService 類別。 在此程式代碼中,收到的通知訊息會寫入主控台。 此外,會叫用 TableOperation 類別內的 TableOp 方法來執行 Select 作業。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)] public class NotificationService : OracleEBSBindingNamespace.OracleEBSBindingService { public override void Notification(Notification request) { Console.WriteLine("\nNew Notification Received"); Console.WriteLine("*************************************************"); Console.WriteLine(request.Info); Console.WriteLine(request.Source); Console.WriteLine(request.Type); Console.WriteLine("*************************************************"); TableOperation Ops = new TableOperation(); Ops.TableOp(); } }您必須實作下列類別,才能傳遞 Oracle E-Business Suite 的憑證。 在應用程式的後一個部分中,您將具現化此類別以傳遞認證。
class NotificationCredentials : 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 NotificationCredentials(); clone.UserName.UserName = this.UserName.UserName; clone.UserName.Password = this.UserName.Password; return clone; } }建立 OracleEBSBinding ,並藉由指定系結屬性來設定配接器以接收查詢通知。 您可以在程式代碼中明確執行此動作,或在組態中以宣告方式執行此動作。 您至少必須指定 InboundOperationType 和 NotificationStatement 系結 屬性。
OracleEBSBinding binding = new OracleEBSBinding(); binding.InboundOperationType = InboundOperation.Notification; binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'"; binding.NotifyOnListenerStart = true; binding.NotificationPort = 10;這很重要
NotificationPort 系結屬性的值必須設定為與您已經新增至 Windows 防火牆例外清單的相同埠號碼。 如需如何將埠新增至 Windows 防火牆例外狀況清單的指示,請參閱 https://go.microsoft.com/fwlink/?LinkID=196959。
這很重要
如果您未設定 NotificationPort 系結屬性,配接器會假設此系結屬性的預設值為 -1。 在這種情況下,您必須完全停用 Windows 防火牆以接收通知訊息。
藉由具現化您在步驟 4 中建立的 NotificationCredentials 類別,指定 Oracle E-Business Suite 認證。
NotificationCredentials credentials = new NotificationCredentials(); credentials.UserName.UserName = "<Enter user name here>"; credentials.UserName.Password = "<Enter password here>";建立在步驟 3 中建立之 WCF 服務的實例。
// create service instance NotificationService service = new NotificationService();使用 WCF 服務和基底連線 URI 建立 System.ServiceModel.ServiceHost 的實例。 您也必須在這裡指定認證。
// Enable service host Uri[] baseUri = new Uri[] { new Uri("oracleebs://ebs_instance_name") }; ServiceHost serviceHost = new ServiceHost(service, baseUri); serviceHost.Description.Behaviors.Add(credentials);將服務端點新增至服務主機。 要達成此目的:
使用在步驟 5 中建立的系結。
指定包含認證的連線 URI,並視需要指定輸入識別碼。
將合約指定為 「Notification_」。
// Add service endpoint: be sure to specify Notification_ as the contract Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name?"); serviceHost.AddServiceEndpoint("Notification_", binding, ConnectionUri);
若要接收通知訊息,請開啟服務主機。
// Open the service host to begin receiving notifications serviceHost.Open();若要停止接收通知,請關閉服務主機。
serviceHost.Close();
範例
下列範例示範 .NET 應用程式,以接收 ACCOUNTACTIVITY 數據表的通知訊息。
備註
下列代碼段會具現化 TableOperation.cs 類別,並叫用 TableOp 方法。 類別和 方法會在步驟 1 中說明。
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 Notification_ServiceModel
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class NotificationService : OracleEBSBindingNamespace.OracleEBSBindingService
{
public override void Notification(Notification request)
{
Console.WriteLine("\nNew Notification Received");
Console.WriteLine("*************************************************");
Console.WriteLine(request.Info);
Console.WriteLine(request.Source);
Console.WriteLine(request.Type);
Console.WriteLine("*************************************************");
TableOperation Ops = new TableOperation();
Ops.TableOp();
}
}
class NotificationCredentials : 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 NotificationCredentials();
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 receiving notifications...");
Console.ReadLine();
OracleEBSBinding binding = new OracleEBSBinding();
binding.InboundOperationType = InboundOperation.Notification;
binding.NotificationStatement = "SELECT TID,ACCOUNT,PROCESSED FROM APPS.ACCOUNTACTIVITY WHERE PROCESSED = 'n'";
binding.NotifyOnListenerStart = true;
binding.NotificationPort = 10;
// 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") };
NotificationCredentials credentials = new NotificationCredentials();
credentials.UserName.UserName = "<Enter user name here>";
credentials.UserName.Password = "<Enter password here>";
Console.WriteLine("Opening service host...");
NotificationService service = new NotificationService();
serviceHost = new ServiceHost(service, baseUri);
serviceHost.Description.Behaviors.Add(credentials);
serviceHost.AddServiceEndpoint("Notification_", binding, ConnectionUri);
serviceHost.Open();
Console.WriteLine("Service host opened...");
Console.WriteLine("Waiting for notification...");
Console.WriteLine("\nHit <RETURN> to stop receiving notification");
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();
}
}
}
}