使用带有 WCF 通道模型的 SELECT 语句轮询 Oracle 电子商务套件

您可以通过使用 SELECT 语句来配置 Oracle 电子商务适配器来接收定期的数据更改消息,以便持续轮询 Oracle 电子商务套件中的接口表、接口视图、表和视图。 您可以将 SELECT 语句指定为该适配器定期执行的轮询语句,以轮询 Oracle 电子商务套件。 你还可以指定在执行轮询语句后适配器执行的轮询后 PL/SQL 代码块。

若要启用轮询,必须指定特定的绑定属性,如本主题中所述。 有关适配器如何支持轮询的详细信息,请参阅对 使用轮询的入站调用的支持

使用 Oracle 电子商务套件适配器绑定属性配置轮询操作

下表总结了用于配置适配器以接收数据更改消息的 Oracle 电子商务适配器绑定属性。 在运行轮询应用程序时,必须指定这些绑定属性。

绑定属性 说明
InboundOperationType 指定是否要执行 轮询通知 入站操作。 默认值为 轮询
PolledDataAvailableStatement 指定适配器执行的 SQL 语句,以确定是否有任何数据可用于轮询。 只有在记录可用时,才会执行为 PollingInput 绑定属性指定的 SELECT 语句。
PollingInterval 指定 Oracle 电子商务适配器执行为 PolledDataAvailableStatement 绑定属性指定的语句的时间间隔(以秒为单位)。 默认为 30 秒。 轮询间隔确定连续轮询之间的时间间隔。 如果在指定的时间间隔内执行该语句,则适配器将在间隔中休眠剩余时间。
PollingInput 指定轮询语句。 若要使用 SELECT 语句进行轮询,必须为此绑定属性指定 SELECT 语句。 默认值为 NULL。

必须为 PollingInput 绑定属性指定值才能启用轮询。 仅当有可用于轮询的数据(由 PolledDataAvailableStatement 绑定属性确定)时,才会执行轮询语句。
PollingAction 指定轮询操作的操作。 您可以使用 "添加适配器服务引用" Visual Studio 插件来确定为操作生成的服务接口的轮询操作。
PostPollStatement 指定执行 PollingInput 绑定属性指定的语句后执行的语句块。
PollWhileDataFound 指定 Oracle 电子商务适配器是否忽略轮询间隔,并持续执行该轮询语句(如果正在轮询的表中有可用数据)。 如果表中没有可用数据,则适配器将恢复为在指定的轮询间隔内执行轮询语句。 默认值为 false。

有关这些属性的更完整说明,请参阅 了解用于 Oracle 电子商务套件的 BizTalk 适配器绑定属性。 有关如何使用 Oracle 电子商务适配器轮询 Oracle 数据库的完整说明,请参阅本主题的其余部分。

本主题演示轮询的方式

在本主题中,为了演示 Oracle 电子商务适配器如何支持使用 SELECT 语句接收数据更改消息,您需要在应用程序对象库应用程序中轮询MS_SAMPLE_EMPLOYEE接口表。 此表是在运行随示例一起提供的 create_apps_artifacts .sql 脚本时创建的,用于在 Oracle 电子商务套件中创建这些对象。

若要演示轮询操作,请执行以下操作:

  • 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 电子商务套件接收基于轮询的数据更改消息

  • PostPollStatement 绑定属性中指定 DELETE 语句。 此语句将从 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 适配器的示例。 基于本主题的示例 SelectPolling_ChannelModel也随 Oracle 电子商务适配器示例一起提供。

使用 WCF 通道模型接收用于轮询操作的入站消息

本部分提供有关如何使用 Oracle 电子商务适配器编写 .NET 应用程序 (通道模型) 来接收入站轮询消息的说明。

从适配器接收轮询消息

  1. 在 Visual Studio 中创建 Microsoft Visual c #®项目。 对于本主题,请创建一个控制台应用程序。

  2. 在解决方案资源管理器中,添加对、 Microsoft.ServiceModel.ChannelsSystem.ServiceModel 、和 System.Runtime.Serialization 的引用 Microsoft.Adapters.OracleEBS

  3. 打开 Program .cs 文件,并添加以下命名空间:

    • Microsoft.Adapters.OracleEBS

    • System.ServiceModel

    • System.ServiceModel.Description

    • System.ServiceModel.Channels

    • System.Xml

  4. 指定连接 URI。 有关适配器连接 URI 的详细信息,请参阅 创建 Oracle 电子商务套件连接 uri

    Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name");  
    
  5. 创建 OracleEBSBinding 的实例,并设置配置轮询所需的绑定属性。 必须至少设置 InboundOperationTypePolledDataAvailableStatementPollingInputPollingAction 绑定属性。 有关用于配置轮询的绑定属性的详细信息,请参阅 对使用轮询的入站调用的支持

    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";  
    
  6. 由于要轮询接口表,因此还必须设置应用程序上下文。 有关设置应用程序上下文所需的应用程序上下文和绑定属性的详细信息,请参阅 设置应用程序上下文

    binding.OracleUserName = "<Enter user name here>";  
    binding.OraclePassword = "<Enter password here>";  
    binding.OracleEBSResponsibilityName = "<Enter responsibility here>";  
    
  7. 创建绑定参数集合并设置凭据。

    ClientCredentials credentials = new ClientCredentials();  
    credentials.UserName.UserName = "<Enter user name here>";  
    credentials.UserName.Password = "<Enter password here>";  
    
    BindingParameterCollection bindingParams = new BindingParameterCollection();  
    bindingParams.Add(credentials);  
    
  8. 创建一个通道侦听器并将其打开。 可以通过对OracleEBSBinding调用BuildChannelListener < IInputChannel >方法来创建侦听器。

    IChannelListener<IInputChannel> listener = binding.BuildChannelListener<IInputChannel>(connectionUri, bindingParams);  
    listener.Open();  
    
  9. 通过对侦听器调用AcceptChannel方法并打开它来获取IInputChannel通道。

    IInputChannel channel = listener.AcceptChannel();  
    channel.Open();  
    
  10. 对通道调用 Receive ,以从适配器获取下一条入站消息。

    Message message = channel.Receive();  
    
  11. 使用入站操作返回的结果集。 您可以使用 XmlReaderXmlDictionaryWriter来使用消息。

    XmlReader reader = message.GetReaderAtBodyContents();  
    
  12. 完成处理请求后,关闭通道。

    channel.Close()  
    

    重要

    完成处理入站操作后,必须关闭通道。 未能关闭通道可能会影响代码的行为。

  13. 完成接收数据更改消息后关闭侦听器。

    listener.Close()  
    

    重要

    关闭侦听器不会关闭使用侦听器创建的通道。 必须显式关闭使用侦听器创建的每个通道。

示例

下面的示例演示轮询 MS_SAMPLE_EMPLOYEE 接口表的轮询应用程序。 PollingInput属性包含用于从 MS_SAMPLE_EMPLOYEE 表中读取所有数据的 select 语句,并且 post 轮询语句将删除同一个表中的所有数据。 轮询消息将写入 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();  
                }  
            }  
        }  
    }  
}  

另请参阅

使用 WCF 通道模型开发 Oracle 电子商务套件应用程序