可以将 Oracle E-Business 适配器配置为使用 SELECT 语句连续轮询 Oracle E-Business Suite 中的接口表、接口视图、表和视图来接收定期的数据更改消息。 可以将 SELECT 语句指定为适配器定期执行的轮询语句来轮询 Oracle 电子商务套件。 可以指定一个适配器在执行轮询语句后执行的 PL/SQL 代码块。
若要启用轮询,必须指定本主题中所述的某些绑定属性。 有关适配器如何支持轮询的详细信息,请参阅 对使用轮询的入站呼叫的支持。
使用 Oracle E-Business Suite 适配器绑定属性配置轮询操作
下表汇总了用于配置适配器以接收数据更改消息的 Oracle E-Business 适配器绑定属性。 在运行轮询应用程序时,必须指定这些绑定属性。
| Binding 属性 | DESCRIPTION |
|---|---|
| InboundOperationType | 指定是要执行 轮询 还是 通知 入站作业。 默认值为 轮询。 |
| 数据可用性声明 | 指定适配器执行的 SQL 语句,以确定是否有任何数据可用于轮询。 仅当记录可用时,将执行为 PollingInput 绑定属性指定的 SELECT 语句。 |
| PollingInterval | 指定 Oracle E-Business 适配器执行 为 PolledDataAvailableStatement 绑定属性指定的语句的间隔(以秒为单位)。 默认值为 30 秒。 轮询间隔定义了连续轮询之间的时间间隔。 如果语句在指定间隔内执行,则适配器会在间隔的剩余时间内休眠。 |
| PollingInput | 指定轮询语句。 若要使用 SELECT 语句轮询,必须为此绑定属性指定 SELECT 语句。 默认值为 null。 必须为 PollingInput 绑定属性指定一个值才能启用轮询。 仅当有数据可用于轮询时,才会执行轮询语句,该数据由 PolledDataAvailableStatement 绑定属性确定。 |
| PollingAction | 指定轮询操作的动作。 可以使用“添加适配器服务引用 Visual Studio 插件”从为操作生成的服务接口确定轮询操作。 |
| 投票后声明 | 指定在执行 PollingInput 绑定属性指定的语句后执行的语句块。 |
| PollWhileDataFound | 指定 Oracle E-Business 适配器是否忽略轮询间隔并连续执行轮询语句(如果正在轮询的表中的数据可用)。 如果表中没有可用数据,适配器将还原为按指定的轮询间隔执行轮询语句。 默认值为 false。 |
有关这些属性的更完整说明,请参阅 有关 Oracle 电子商务套件绑定属性的 BizTalk 适配器的信息。 有关如何使用 Oracle 电子商务适配器轮询 Oracle 数据库的完整说明,请阅读本主题的其余部分。
本主题如何演示轮询
在本主题中,为了演示 Oracle E-Business 适配器如何支持使用 SELECT 语句接收数据更改消息,请在应用程序对象库应用程序中轮询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 电子商务套件。 也就是说,适配器发送通过 IInputChannel 通道形状收到的轮询请求消息。 轮询请求消息包含 PollingInput 绑定属性指定的查询的结果集。 可以通过两种方式之一处理轮询消息:
若要使用节点值流式处理来使用消息,必须在响应消息上调用 WriteBodyContents 方法,并将其传递给实现节点值流式处理的 XmlDictionaryWriter 。
若要使用节点流式处理消息,可以在响应消息上调用 GetReaderAtBodyContents 以获取 XmlReader。
关于本主题中使用的示例
本主题中的示例查询MS_SAMPLE_EMPLOYEE接口表。 生成表的脚本随示例一起提供。 有关示例的详细信息,请参阅 Oracle EBS 适配器的示例。 Oracle E-Business 适配器示例中还提供了一个示例 SelectPolling_ChannelModel,它是基于本主题的。
使用 WCF 通道模型接收用于轮询操作的入站消息
本部分提供有关如何使用 Oracle 电子商务适配器编写 .NET 应用程序(通道模型)以接收入站轮询消息的说明。
从适配器接收投票消息
在 Visual Studio 中创建Microsoft Visual C# ® 项目。 对于本主题,请创建控制台应用程序。
在解决方案资源管理器中,添加对
Microsoft.Adapters.OracleEBS、Microsoft.ServiceModel.Channels、System.ServiceModel和System.Runtime.Serialization的引用。打开Program.cs文件并添加以下命名空间:
Microsoft.Adapters.OracleEBSSystem.ServiceModelSystem.ServiceModel.DescriptionSystem.ServiceModel.ChannelsSystem.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();在通道上调用 Receive ,从适配器获取下一个入站消息。
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();
}
}
}
}
}