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

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

参数方向 强类型 REF CURSOR 弱类型 REF CURSOR
IN 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 out [PROC_NS].[PARAM_NAME]RECORD[] [PARAM_NAME]

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

弱类型泛型记录集。
IN OUT 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 参数是在基于 SCHEMA、PACKAGE 以及使用它们的过程或函数的名称的唯一命名空间中生成的。 对于 /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 数据库应用程序