使用 WCF 通道模型调用 Oracle 数据库上的操作

可以使用 IRequestChannelIOutputChannel 形状对 Oracle 数据库适配器调用操作,以将消息发送到适配器。 基本模式是使用绑定 (OracleDBBinding) 和从连接 URI 创建的终结点,为所需的通道形状创建通道工厂。 然后,创建一个 Message 实例,该实例表示符合目标操作的消息架构的 SOAP 消息。 然后,可以使用从通道工厂创建的通道将此 消息 发送到 Oracle 数据库适配器。 如果使用的是 IRequestChannel,则会收到响应。 如果在 Oracle 数据库上执行操作时遇到问题,Oracle 数据库适配器将引发 Microsoft.ServiceModel.Channels.Common.TargetSystemException

有关如何在 WCF 中使用 IRequestChannel 发送操作的概述,请参阅 中的 https://go.microsoft.com/fwlink/?LinkId=106081“客户端 Channel-Level 编程”。

本主题中的各节提供的信息有助于使用 WCF 通道模型对 Oracle 数据库适配器调用操作。

创建和使用出站操作的消息

若要在 Oracle 数据库适配器上调用操作,请使用 IRequestChannelIOutputChannel 发送目标操作的请求消息。 如果使用 IRequestChannel ,适配器将在响应消息中返回操作的结果。

有关请求和响应消息架构以及每个操作的消息操作的详细信息,请参阅 用于 Oracle 数据库的 BizTalk 适配器的消息和消息架构

创建请求消息和使用响应消息的方式决定了适配器是执行节点流式处理还是节点值流式处理。 这反过来又决定了是否为支持的操作执行 LOB 数据的端到端流式处理。

创建请求消息

可以通过以下两种方式之一创建请求消息:

  • 若要创建可用于节点值流式处理的消息,必须在实现节点值流式处理的 XmlBodyWriter 中传递消息正文。

  • 若要创建可用于节点流式处理的消息,可以在 XmlReader 中传递消息正文。

    通常使用节点值流式处理来支持请求消息中的 Oracle LOB 数据的端到端流式处理。 唯一支持此功能的操作是 UpdateLOB。

使用响应消息

可以通过以下两种方式之一使用响应消息:

  • 若要使用节点值流式处理使用消息,必须在响应消息上调用 WriteBodyContents 方法,并向其传递实现节点值流式处理的 XmlDictionaryWriter

  • 若要使用节点流式处理使用消息,可以在响应消息上调用 GetReaderAtBodyContents 以获取 XmlReader

    通常使用节点值流式处理来支持响应消息中的 Oracle LOB 数据的端到端流式处理。 有许多操作支持此功能。

LOB 数据和消息流式处理支持

有关 Oracle 数据库适配器如何支持对 LOB 数据进行流式处理的详细信息,请参阅 Oracle 数据库适配器中的流式处理大型对象数据类型

有关在代码中实现节点值流式处理以支持 LOB 数据的端到端流式处理的详细信息,请参阅 使用 WCF 通道模型流式处理 Oracle 数据库 LOB 数据类型

WCF 通道模型中出站操作的事务支持。

适配器执行在 Oracle 数据库的专用事务内调用的每个操作。 可以通过设置 TransactionIsolationLevel 绑定属性来控制这些事务的隔离级别。

关于本主题中使用的示例

本主题中的示例使用 SCOTT。ACCOUNTACTIVITY 表。 SDK 示例提供了生成这些项目的脚本。 有关 SDK 示例的详细信息,请参阅 SDK 中的示例

如何使用通道调用操作?

若要使用 IRequestChannel 调用操作,请执行以下步骤。

如何使用 IRequestChannel 实例调用操作

  1. (ChannelFactory<IRequestChannel>) 生成通道工厂。 为此,必须指定 oracleDBBinding) (绑定和终结点地址。 可以在代码中以命令方式或在配置中以声明方式指定绑定和终结点地址。 有关如何在配置中指定绑定和终结点地址的详细信息,请参阅 使用 Oracle 数据库创建通道

    // Create a binding
    OracleDBBinding binding = new OracleDBBinding();
    // Create an endpoint address by using the connection URI
    EndpointAddress address = new EndpointAddress("oracledb://ADAPTER");
    // Create the channel factory
    ChannelFactory<IRequestChannel> factory = new ChannelFactory<IRequestChannel>(binding, address);
    
  2. 使用 ClientCredentials 属性设置通道工厂的用户名密码凭据。

    factory.Credentials.UserName.UserName = "SCOTT";
    factory.Credentials.UserName.Password = "TIGER";
    
  3. 打开通道工厂。

    factory.Open();
    
  4. 从工厂获取通道并将其打开。

    IRequestChannel channel = factory.CreateChannel();
    channel.Open();
    
  5. 为目标操作创建 Message 实例。 请确保已指定目标操作的消息操作。 在此示例中,通过创建 基于文件的 XmlReader 传递消息正文。 目标操作是 SCOTT/EMP 表上的 Select 操作。

    XmlReader readerIn = XmlReader.Create("SelectAllActivity.xml");
    Message messageIn = Message.CreateMessage(MessageVersion.Default,
        "http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/ACCOUNTACTIVITY/Select",
        readerIn);
    
  6. 在通道上调用 Request 方法,将消息发送到 Oracle 数据库适配器并接收答复。 如果 Oracle 数据库遇到异常,适配器将引发 TargetSystemException。 (非 Oracle exceptions 可能存在其他异常。) 可以从 TargetSystemExceptionInnerException.Message 属性获取 Oracle 错误的说明。

    try
    {
        Message messageOut = channel.Request(messageIn);
    }
    catch (Exception ex)
    {
        // handle exception
    }
    
  7. 处理响应。 在此示例中,对响应消息调用 GetReaderAtBodyContents 以获取消息正文。

    XmlReader readerOut = messageOut.GetReaderAtBodyContents();
    
  8. 处理完响应消息后,关闭读取器和消息。

    readerOut.Close();
    messageOut.Close();
    
  9. 使用完通道和通道工厂后,请关闭它们。 关闭工厂将关闭使用它创建的所有通道。

    channel.Close()
    factory.Close();
    
    

    按照相同的步骤使用 IOutputChannel 形状发送消息,但除外:

  • 在步骤 1 中创建 ChannelFactory<IOutputChannel>

  • 在步骤 6 中,在通道上调用 Send 方法。 channel.Send(messageIn);.

  • 没有为 IOutputChannel 返回任何响应消息。

示例

以下示例演示如何使用 IRequestChannel 通道调用 Select 操作。 使用 XmlReader 使用 Select 响应消息,返回的记录数将写入控制台。

using System;
using System.Collections.Generic;
using System.Text;

using System.ServiceModel;
using System.ServiceModel.Channels;
using Microsoft.ServiceModel.Channels;
using Microsoft.Adapters.OracleDB;
using System.Xml;
using System.IO;
using System.Runtime.Serialization;

namespace RequestChanneSample
{
    class Program
    {
        static void Main(string[] args)
        {
            // The Select operation request message
            const string selectRequestString =
                "\<Select xmlns=\"http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/ACCOUNTACTIVITY\"\>" +
                    "<COLUMN_NAMES>*</COLUMN_NAMES>" +
                    "<FILTER>ACCOUNT = 100002</FILTER>" +
                "</Select>";
            try
            {
                // Create binding -- specify binding properties before you open the factory.
                OracleDBBinding odbBinding = new OracleDBBinding();

                // Create address.
                EndpointAddress odbAddress = new EndpointAddress("oracledb://ADAPTER/");

                // Create channel factory from binding and address.
                ChannelFactory<IRequestChannel> factory =
                    new ChannelFactory<IRequestChannel>(odbBinding, odbAddress);

                // Specify credentials
                factory.Credentials.UserName.UserName = "SCOTT";
                factory.Credentials.UserName.Password = "TIGER";

                // Open the factory.
                factory.Open();

                // Get a channel.
                IRequestChannel channel = factory.CreateChannel();

                // Open the channel.
                channel.Open();

                // Create the request message from the string
                StringReader strReader = new StringReader(selectRequestString);
                XmlReader readerIn = XmlReader.Create(strReader);

                Message requestMessage = Message.CreateMessage(MessageVersion.Default,
                    "http://Microsoft.LobServices.OracleDB/2007/03/SCOTT/Table/ACCOUNTACTIVITY/Select",
                    readerIn);

                Send the message and get a respone
                Message responseMessage = channel.Request(requestMessage);

                // Get an XmlReader from the message
                XmlReader readerOut = (XmlReader) responseMessage.GetReaderAtBodyContents();

                // Count the number of records returned and write to the console.
                readerOut.MoveToContent();
                int numberOfRecordsReturned = 0;
                while (readerOut.Read())
                {
                    if (readerOut.NodeType == XmlNodeType.Element && readerOut.Name == "ACCOUNTACTIVITYRECORDSELECT")
                        numberOfRecordsReturned++;
                }

                Console.WriteLine("{0} records returned.", numberOfRecordsReturned);

                // Close the output reader and message
                readerOut.Close();
                responseMessage.Close();

                //Close channel
                channel.Close();

                //Close the factory
                factory.Close();
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

另请参阅

使用 WCF 通道模型开发 Oracle 数据库应用程序