使用 WCF 服務模型接收 Oracle E-Business Suite 資料庫變更通知
本主題示範如何設定 Oracle E-Business 配接器,以接收來自 Oracle 資料庫的查詢通知訊息。 若要示範通知,請考慮具有 「Processed」 資料行的資料表 ACCOUNTACTIVITY。 當新記錄插入此資料表時,Status 資料行的值會設定為 「n」。 您可以使用 SQL 語句來擷取具有 「Processed」 資料行的所有記錄,以設定配接器以接收通知。 您可以指定 NotificationStatement 系結屬性的 SQL 語句來執行此動作。 配接器用戶端收到通知之後,它可以包含邏輯,以在 Oracle 資料庫上執行任何後續工作。 在此範例中,為了簡單起見,配接器用戶端會將資料表中的所有記錄列出為 「n」。
使用 Oracle E-Business 配接器系結屬性設定通知
下表摘要說明您用來設定從 Oracle E-Business Suite 接收通知的 Oracle E-Business 配接器系結屬性。 在執行 .NET 應用程式以接收通知時,您必須指定這些系結屬性。
Binding 屬性 | Description |
---|---|
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 服務模型接收查詢通知
本節提供如何撰寫 .NET 應用程式以使用 Oracle E-Business 配接器接收查詢通知的指示。
接收查詢通知
使用 [新增配接器服務參考外掛程式],在ACCOUNTACTIVITY資料表上產生[選取] 作業的 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();
}
}
}
}