使用 SELECT 语句通过 WCF 服务模型查询 Oracle E-Business Suite 电子商务套件

可以将 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脚本。 运行此脚本后,下一个轮询操作将提取插入到表中的新记录。

在 WCF 服务模型中设置轮询

若要通过 WCF 服务模型使用 Oracle 电子商务适配器轮询接口表,必须:

  • 为 MS_SAMPLE_EMPLOYEE 接口表上的 轮询 操作生成 WCF 服务协定(接口)。 为此,可以使用“添加适配器服务引用插件”。

  • 从此接口实现 WCF 服务。

  • 使用服务主机(System.ServiceModel.ServiceHost)托管此 WCF 服务。

关于本主题中使用的示例

本主题中的示例查询MS_SAMPLE_EMPLOYEE接口表。 生成表的脚本随示例一起提供。 有关示例的详细信息,请参阅 Oracle EBS 适配器的示例。 Oracle E-Business 适配器示例中也提供了一个名为 SelectPolling_ServiceModel 的示例,这是基于本主题的。

WCF 服务协定和类

可以使用“添加适配器服务引用插件”来创建用于轮询操作的 WCF 服务契约(接口)和支持类。 有关生成 WCF 服务协定的详细信息,请参阅 为 Oracle E-Business Suite 解决方案项目生成 WCF 客户端或 WCF 服务协定

WCF 服务协定(接口)

以下代码显示了为 MS_SAMPLE_EMPLOYEE 接口表上的 轮询 操作生成的 WCF 服务契约(接口)。

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/", ConfigurationName="InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE")]
public interface InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE {

    // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE_EMPLOYEE) of message Poll
    // does not match the default value (https://schemas.microsoft.com/OracleEBS/)
    [System.ServiceModel.OperationContractAttribute(IsOneWay=true, Action="InterfaceTables/Poll/FND/APPS/MS_SAMPLE_EMPLOYEE")]
    void Poll(Poll request);
}

消息合同

下面是MS_SAMPLE_EMPLOYEE接口表中的 轮询 操作的消息协定。

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.MessageContractAttribute(WrapperName="Poll", WrapperNamespace="http://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE" +
    "_EMPLOYEE", IsWrapped=true)]
public partial class Poll {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE" +
        "_EMPLOYEE", Order=0)]
    public schemas.microsoft.com.OracleEBS._2008._05.TableViewRecord.APPS.MS_SAMPLE_EMPLOYEE.SelectRecord[] DATA;

    public Poll() {
    }

    public Poll(schemas.microsoft.com.OracleEBS._2008._05.TableViewRecord.APPS.MS_SAMPLE_EMPLOYEE.SelectRecord[] DATA) {
        this.DATA = DATA;
    }
}

WCF 服务类

添加适配器服务引用插件还会生成一个文件,该文件包含从服务协定(接口)实现的 WCF 服务类的存根。 文件的名称OracleEBSBindingService.cs。 可以将逻辑直接插入到此类以处理轮询操作。 以下代码显示了由“添加适配器服务引用插件”生成的 WCF 服务类。

namespace OracleEBSBindingNamespace {

    public class OracleEBSBindingService : InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE {

        // CODEGEN: Generating message contract since the wrapper namespace (https://schemas.microsoft.com/OracleEBS/2008/05/InterfaceTables/FND/APPS/MS_SAMPLE_EMPLOYEE) of message Poll
        // does not match the default value (https://schemas.microsoft.com/OracleEBS/)
        public virtual void Poll(Poll request) {
            throw new System.NotImplementedException("The method or operation is not implemented.");
        }
    }
}

使用 SELECT 语句接收轮询操作的入站消息

本部分介绍如何编写 .NET 应用程序以使用 Oracle E-Business 适配器接收入站轮询消息。

使用 SELECT 语句接收轮询消息

  1. 使用“添加适配器服务引用插件”生成 MS_SAMPLE_EMPLOYEE 接口表中 轮询 操作的 WCF 服务契约(接口)和辅助类。 有关详细信息,请参阅 为 Oracle 电子商务套件解决方案项目生成 WCF 客户端或 WCF 服务协定。 可以选择在生成服务协定和帮助程序类时指定绑定属性。 这可以保证在生成的配置文件中正确设置它们。

  2. 从步骤 1 中生成的接口和帮助程序类实现 WCF 服务。 如果在处理从轮询操作接收的数据时遇到错误,此类的Poll方法可能会引发异常来中止事务,否则该方法不返回任何内容。 必须按如下所示将 WCF 服务类属性化:

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    

    Poll 方法中,可以直接实现应用程序逻辑。 可以在OracleEBSBindingService.cs中找到此类。 此示例中的此代码子类为 OracleEBSBindingService 类。 在此代码中,轮询消息被接收后写入控制台。

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    
    public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
    {
        public override void Poll(Poll request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Emp No\tName\tDesignation\tSalary");
            for (int i = 0; i < request.DATA.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.DATA[i].EMP_NO,
                request.DATA[i].NAME,
                request.DATA[i].DESIGNATION,
                request.DATA[i].SALARY);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }
    
  3. 必须实现以下类,以避免在 URI 中传递凭据。 在应用程序的后期部分中,您将实例化这个类以传递凭证。

    class PollingCredentials : 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 PollingCredentials();
            clone.UserName.UserName = this.UserName.UserName;
            clone.UserName.Password = this.UserName.Password;
            return clone;
        }
    }
    
  4. 通过指定绑定属性创建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";
    
  5. 由于正在轮询接口表,因此还必须设置应用程序上下文。 有关设置应用程序上下文所需的应用程序上下文和绑定属性的详细信息,请参阅 “设置应用程序上下文”。

    binding.OracleUserName = "myOracleEBSUserName";
    binding.OraclePassword = "myOracleEBSPassword";
    binding.OracleEBSResponsibilityName = "myOracleEBSResponsibility";
    
  6. 通过实例化在步骤 3 中创建的 PollingCredentials 类来指定 Oracle E-Business Suite 凭据。

    PollingCredentials credentials = new PollingCredentials();
    credentials.UserName.UserName = "<Enter user name here>";
    credentials.UserName.Password = "<Enter password here>";
    
  7. 创建在步骤 2 中创建的 WCF 服务的实例。

    // create service instance
    PollingService service = new PollingService();
    
  8. 使用 WCF 服务和基本连接 URI 创建 System.ServiceModel.ServiceHost 的实例。 基连接 URI 不能包含入站 ID(如果指定)。 还必须在此处传递凭据。

    // Enable service host
    Uri[] baseUri = new Uri[] { new Uri("oracleebs://ebs_instance_name") };
    ServiceHost serviceHost = new ServiceHost(service, baseUri);
    serviceHost.Description.Behaviors.Add(credentials);
    
    
  9. 将服务终结点添加到服务主机。 为此,请按以下步骤操作:

    • 使用在步骤 4 中创建的绑定。

    • 指定包含凭据的连接 URI,并根据需要指定入站 ID。

    • 请将合同指定为“InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE”,以便轮询MS_SAMPLE_EMPLOYEE接口表。

      // Add service endpoint: be sure to specify InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE as the contract
      Uri ConnectionUri = new Uri("oracleebs://ebs_instance_name");
      serviceHost.AddServiceEndpoint("InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE", binding, ConnectionUri);
      
  10. 若要接收轮询数据,请打开服务主机。 每当查询返回结果集时,适配器都会返回数据。

    // Open the service host to begin polling
    serviceHost.Open();
    
  11. 若要终止轮询,请关闭服务主机。

    重要

    适配器将继续轮询,直到服务主机关闭。

    serviceHost.Close();
    

示例:

以下示例展示了一个用于轮询MS_SAMPLE_EMPLOYEE接口表的应用程序。 PollingInput 属性包含 select 语句,该语句从MS_SAMPLE_EMPLOYEE表中读取所有数据,post poll 语句将删除同一表中的所有数据。 第一条轮询消息提供来自MS_SAMPLE_EMPLOYEE接口表的所有记录。 后续轮询消息将不包含任何记录,因为轮询后语句会删除这些记录。 在将更多数据添加到MS_SAMPLE_EMPLOYEE接口表之前,不会收到任何轮询消息。 因此,必须用新记录重新更新MS_SAMPLE_EMPLOYEE接口表。 为此,可以运行随示例一起提供的insert_apps_data.sql脚本。 运行此脚本后,下一个轮询操作将提取插入到表中的新记录。 适配器将继续轮询,直到按下 <RETURN> 关闭服务主机。

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 SelectPolling_ServiceModel
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]

    public class PollingService : OracleEBSBindingNamespace.OracleEBSBindingService
    {
        public override void Poll(Poll request)
        {
            Console.WriteLine("\nNew Polling Records Received");
            Console.WriteLine("*************************************************");
            Console.WriteLine("Emp No\tName\tDesignation\tSalary");
            for (int i = 0; i < request.DATA.Length; i++)
            {
                Console.WriteLine("{0}\t{1}\t{2}\t{3}",
                request.DATA[i].EMP_NO,
                request.DATA[i].NAME,
                request.DATA[i].DESIGNATION,
                request.DATA[i].SALARY);
            }
            Console.WriteLine("*************************************************");
            Console.WriteLine("\nHit <RETURN> to stop polling");
        }
    }

    class PollingCredentials : 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 PollingCredentials();
            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 polling...");
                Console.ReadLine();

                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 = "myOracleEBSUserName";
                binding.OraclePassword = "myOracleEBSPassword";
                binding.OracleEBSResponsibilityName = "myOracleEBSResponsibility";

                // 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") };

                PollingCredentials credentials = new PollingCredentials();
                credentials.UserName.UserName = "<Enter user name here>";
                credentials.UserName.Password = "<Enter password here>";

                Console.WriteLine("Opening service host...");
                PollingService service = new PollingService();
                serviceHost = new ServiceHost(service, baseUri);
                serviceHost.Description.Behaviors.Add(credentials);
                serviceHost.AddServiceEndpoint("InterfaceTables_FND_APPS_MS_SAMPLE_EMPLOYEE", binding, ConnectionUri);
                serviceHost.Open();
                Console.WriteLine("Service host opened...");
                Console.WriteLine("Polling started...");
                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();
            }
        }
    }
}

另请参阅

使用 WCF 服务模型轮询 Oracle 电子商务套件