使用 WCF 服务模型在 Oracle 数据库中运行 REF CURSORS 操作

REF CURSOR 是一种 Oracle PL/SQL 数据类型,表示指向 Oracle 数据库中结果集的指针。 适用于 Oracle 数据库的 Microsoft BizTalk 适配器支持过程、函数和包中的 REF CURSOR 参数。 REF CURSOR 参数可以是强类型或弱类型参数,具体取决于它们在过程中或函数中的声明方式。 有关 REF CURSOR 参数如何由 Oracle 数据库适配器表示的详细说明,请参阅 REF CURSORS 的消息架构。下表总结了如何在 WCF 服务模型中表示 REF CURSOR 参数。

参数方向 强类型的 REF CURSOR 弱类型化 REF CURSOR
string [PARAM_NAME]

包含 PL/SQL 块的字符串。 PL/SQL 块必须通过执行“OPEN FOR SELECT”语句或调用函数或过程来返回打开的 REF CURSOR。 问号(?)指示返回参数的 REF CURSOR 的位置。 例如,“BEGIN OPEN? FOR SELECT * FROM MY_TABLE;END“或”BEGIN MY_PROC(PARM1、?、PARM2):END;“。
与强类型相同
out [PROC_NS].[PARAM_NAME]RECORD[] [PARAM_NAME]

强类型记录集。
out [GENERIC_NS].GenRecordRow[] [PARAM_NAME]

弱类型泛型记录集。
进入 输出 IN OUT REF CURSOR 参数拆分为 IN 和 OUT 参数。 IN 参数在方法签名中追加了“_IN”,以将其与 OUT 参数区分开来。 OUT 参数由强类型记录集表示。

string [PARAM_NAME]_IN

out [PROC_NS].[PARAM_NAME]RECORD[] [PARAM_NAME]
IN OUT REF CURSOR 参数拆分为 IN 和 OUT 参数。 IN 参数追加了“_IN”,以将其与 OUT 参数区分开来。 OUT 参数由弱类型记录集表示。

string [PARAM_NAME]_IN

out [GENERIC_NS].GenRecordRow[] [PARAM_NAME]

[PARAM_NAME] = Oracle 数据库中函数或过程定义中的参数的名称;例如 MYREFCURSOR。

[PROC_NS] = 用于包含包、过程或函数参数的唯一命名空间生成;例如,“microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACTIVITY”。

[GENERIC_NS] = 定义泛型记录集的命名空间“microsoft.lobservices.oracledb._2007._03”。

关于本主题中使用的示例

本主题中的示例使用 /SCOTT/Package/ACCOUNT_PKG Oracle PACKAGE。 以下过程来自ACCOUNT_PKG:

PROCEDURE get_activity(inrecs IN SYS_REFCURSOR, status OUT NUMBER, inoutrecs IN OUT activity_ref_type, outrecs OUT SYS_REFCURSOR);  

SDK 示例提供了生成此包的脚本。 有关 SDK 示例的详细信息,请参阅 SDK 中的示例

WCF 服务模型中的 REF CURSOR 参数

以下示例演示为 /SCOTT/Package/ACCOUNT_PKG/GET_ACTIVITY 过程所生成的类和 WCF 客户端。 该过程具有弱类型的 IN 和 OUT REF CURSOR 参数以及强类型的 IN OUT REF CURSOR 参数。

以下是在 WCF 客户端中生成用于调用 GET_ACTIVITY 的方法签名。

public System.Nullable<decimal> GET_ACTIVITY(string INRECS, string INOUTRECS_IN, out microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACTIVITY.INOUTRECSRECORD[] INOUTRECS, out microsoft.lobservices.oracledb._2007._03.GenRecordRow[] OUTRECS);  

GET_ACTIVITY 方法中,IN OUT 参数 INOUTRECS 拆分为两个参数:

  • INOUTRECS_IN是表示 IN REF CURSOR 参数的字符串。

  • INOUTRECS 是一个强类型记录集,表示 OUT REF CURSOR 参数。

    弱类型 OUT 参数 OUTRECS 表示为泛型记录集。 弱类型 IN 参数 INRECS 表示为字符串。

Strongly-Typed OUT REF CURSOR 参数

强类型的 OUT(或 IN OUT) REF CURSOR 参数是在以模式、包及其所用过程或函数的名称为基础生成的唯一命名空间中产生的。 对于 /SCOTT/Package/ACCOUNT_PKG/GET_ACTIVITY 过程,此命名空间为 microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACTIVITY。 类名是通过将参数的名称追加为“RECORD”而构成的,该类由表示 Oracle 字段的属性组成。 下面显示了表示为 INOUTRECS REF CURSOR 参数生成的强类型记录的类的一部分。

namespace microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACTIVITY {  
    using System.Runtime.Serialization;  
  
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]  
    [System.Runtime.Serialization.DataContractAttribute()]  
    public partial class INOUTRECSRECORD : object, System.Runtime.Serialization.IExtensibleDataObject {  
  
        ...  
  
        private System.Nullable<decimal> TIDField;  
  
        ...  
  
        [System.Runtime.Serialization.DataMemberAttribute()]  
        public System.Nullable<decimal> TID {  
            get {  
                return this.TIDField;  
            }  
            set {  
                this.TIDField = value;  
            }  
        }  
  
        ...  
  
    }  
}  

Weakly-Typed OUT REF CURSOR 参数

弱类型的 OUT(或 IN OUT)REF CURSOR 参数由通用记录类表示。 无论函数或过程如何,泛型记录集始终在同一命名空间中生成,并且具有相同的类名。 以下代码显示了泛型记录类 microsoft.lobservices.oracledb._2007._03.GenRecordRow,该类表示 OUTRECS OUT SYS_REFCURSOR 参数(弱类型)的记录。

namespace microsoft.lobservices.oracledb._2007._03 {  
    using System.Runtime.Serialization;  
  
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]  
    [System.Runtime.Serialization.DataContractAttribute()]  
    public partial class GenRecordRow : object, System.Runtime.Serialization.IExtensibleDataObject {  
  
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;  
  
        private microsoft.lobservices.oracledb._2007._03.GenRecordColumn[] GenRecordColumnField;  
  
        public System.Runtime.Serialization.ExtensionDataObject ExtensionData {  
            get {  
                return this.extensionDataField;  
            }  
            set {  
                this.extensionDataField = value;  
            }  
        }  
  
        [System.Runtime.Serialization.DataMemberAttribute()]  
        public microsoft.lobservices.oracledb._2007._03.GenRecordColumn[] GenRecordColumn {  
            get {  
                return this.GenRecordColumnField;  
            }  
            set {  
                this.GenRecordColumnField = value;  
            }  
        }  
    }  
  
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "3.0.0.0")]  
    [System.Runtime.Serialization.DataContractAttribute()]  
    public partial class GenRecordColumn : object, System.Runtime.Serialization.IExtensibleDataObject {  
  
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;  
  
        private string ColumnNameField;  
  
        private string ColumnValueField;  
  
        private string ColumnTypeField;  
  
        public System.Runtime.Serialization.ExtensionDataObject ExtensionData {  
            get {  
                return this.extensionDataField;  
            }  
            set {  
                this.extensionDataField = value;  
            }  
        }  
  
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, EmitDefaultValue=false)]  
        public string ColumnName {  
            get {  
                return this.ColumnNameField;  
            }  
            set {  
                this.ColumnNameField = value;  
            }  
        }  
  
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]  
        public string ColumnValue {  
            get {  
                return this.ColumnValueField;  
            }  
            set {  
                this.ColumnValueField = value;  
            }  
        }  
  
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true, EmitDefaultValue=false, Order=2)]  
        public string ColumnType {  
            get {  
                return this.ColumnTypeField;  
            }  
            set {  
                this.ColumnTypeField = value;  
            }  
        }  
    }  
}  

将 REF CURSOR 参数与 WCF 客户端配合使用

若要使用 WCF 客户端通过 REF CURSOR 参数调用过程或函数,请执行以下作:

  1. 为包含 PL/SQL 块的每个 IN 或 IN OUT REF CURSOR 参数传递字符串,以打开 REF CURSOR。 此块可以执行 OPEN FOR SELECT 语句,也可以调用在 OUT 参数中返回打开的 REF CURSOR 的函数或过程。

  2. 当过程或函数返回时,对返回的 OUT 或 IN OUT REF CURSOR 参数的记录集中的数据进行操作。 记录集将是弱类型 REF CURSOR 参数的通用记录集,或者是强类型 REF CURSOR 参数的强类型记录集。

    有关如何使用 WCF 服务模型调用过程和函数的详细信息,请参阅 使用 WCF 服务模型调用 Oracle 数据库中的函数和过程

    以下示例调用GET_ACTIVITY过程。 它演示了指定 IN REF CURSOR 参数的两种方式:

  • 对于 IN REF CURSOR 参数,指定 OPEN FOR SELECT 语句以返回 ACCOUNT 100001 的活动。

  • 对于 IN OUT REF CURSOR 参数,将调用 /SCOTT/Package/ACCOUNT_PKG/GET_ALL_ACTIVITY 程序。 此过程将打开一个 REF CURSOR,其中包含 ACCOUNTACTIVITY 表中的所有活动,并将其作为 OUT 参数返回。

    该示例还演示了如何从针对强类型和弱类型 REF CURSOR 参数返回的记录集中读取数据。

using System;  
using System.Collections.Generic;  
using System.Text;  
  
// Add WCF, WCF LOB Adapter SDK, and Oracle Database adapter namepaces  
using System.ServiceModel;  
using Microsoft.ServiceModel.Channels;  
using Microsoft.Adapters.OracleDB;  
  
// Include this namespace for WCF LOB Adapter SDK and Oracle Database adapter exceptions  
using Microsoft.ServiceModel.Channels.Common;  
  
// namespaces for strongly-typed and weakly typed REF CURSOR records  
using GET_ACTIVITYns = microsoft.lobservices.oracledb._2007._03.SCOTT.Package.ACCOUNT_PKG.GET_ACTIVITY;  
using GENERICns = microsoft.lobservices.oracledb._2007._03;  
  
// In this sample, INRECS is opened by using an OPEN FOR statement, and  
// INOUTRECS_IN is opened by calling the GET_ALL_ACTIVITY procedure on Oracle.  
  
namespace OracleRefCursorsSM  
{  
    class Program  
    {  
        static void Main(string[] args)  
        {  
            // Create the client  
            SCOTTPackageACCOUNT_PKGClient accountPkgClient =   
                new SCOTTPackageACCOUNT_PKGClient("OracleDBBinding_SCOTT.Package.ACCOUNT_PKG");  
            // Set credentials  
            accountPkgClient.ClientCredentials.UserName.UserName = "SCOTT";  
            accountPkgClient.ClientCredentials.UserName.Password = "TIGER";  
  
            try  
            {  
  
                GET_ACTIVITYns.INOUTRECSRECORD[] strongCursor;  
                GENERICns.GenRecordRow[] weakCursor;  
  
                Console.WriteLine("Opening client");  
                // Open the client  
                accountPkgClient.Open();  
  
                Console.WriteLine("Invoking ACCOUNT_PKG.GET_ACTIVITY");  
                // Get  ACCOUNTACTIVITY records  
                // The IN REF CURSOR is set to all activity for account 100001  
                // The input part of the IN OUT ref cursor calls GET_ALL_ACTIVITY  
                // The weakly-typed OUT REF CURSOR parameter returns a list of activity for account 100001  
                // The strongly-typed IN OUT REF CURSOR parameter returns a list of all activity  
                string inRecsString = "BEGIN OPEN ? FOR SELECT * FROM ACCOUNTACTIVITY WHERE ACCOUNT=100001; END;";  
                string inoutRecsString = "BEGIN ACCOUNT_PKG.GET_ALL_ACTIVITY(?); END;";  
  
                accountPkgClient.GET_ACTIVITY(  
                                inRecsString,  
                                inoutRecsString,  
                                out strongCursor,  
                                out weakCursor);  
  
                // Display strong ref cursor (all activity)  
                Console.WriteLine("\nList of all activity returned (strong ref cursor)");  
                Console.WriteLine("Tx Id\tAccount\tAmount\tDate\t\t\tDescription");  
                for (int i = 0; i < strongCursor.Length; i++)  
                {  
                    Console.WriteLine("{0}\t{1}\t{2:C}\t{3}\t{4}",strongCursor[i].TID,  
                        strongCursor[i].ACCOUNT,   
                        strongCursor[i].AMOUNT,   
                        strongCursor[1].TRANSDATE,  
                        strongCursor[i].DESCRIPTION);  
                }  
  
                // Display weak ref cursor (account 100001)  
                Console.WriteLine("\nList of activity for account 100001 returned (weak ref cursor)");  
                Console.WriteLine("Tx Id\tAmount\tDate\t\t\tDescription");  
                for (int i = 0; i < weakCursor.Length; i++)  
                {  
                    Console.WriteLine("{0}\t{1:C}\t{2}\t{3}", weakCursor[i].GenRecordColumn[0].ColumnValue,  
                        weakCursor[i].GenRecordColumn[2].ColumnValue,  
                        weakCursor[i].GenRecordColumn[4].ColumnValue,  
                        weakCursor[i].GenRecordColumn[3].ColumnValue);  
                }  
  
                Console.WriteLine("\nHit <RETURN> to finish");  
                Console.ReadLine();  
            }  
            catch (TargetSystemException tex)  
            {  
                Console.WriteLine("Exception occurred on the Oracle Database");  
                Console.WriteLine(tex.InnerException.Message);  
            }  
            catch (ConnectionException cex)  
            {  
                Console.WriteLine("Exception occurred connecting to the Oracle Database");  
                Console.WriteLine(cex.InnerException.Message);  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Exception is: " + ex.Message);  
                if (ex.InnerException != null)  
                {  
                    Console.WriteLine("Inner Exception is: " + ex.InnerException.Message);  
                }  
                throw ex;  
            }  
            finally  
            {  
                // Close the client  
                accountPkgClient.Close();  
            }  
        }  
    }  
}  

另请参阅

使用 WCF 服务模型开发 Oracle 数据库应用程序