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]_INout [PROC_NS].[PARAM_NAME]RECORD[] [PARAM_NAME] |
IN OUT REF CURSOR 参数拆分为 IN 和 OUT 参数。 IN 参数追加了“_IN”,以将其与 OUT 参数区分开来。 OUT 参数由弱类型记录集表示。string [PARAM_NAME]_INout [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 参数调用过程或函数,请执行以下作:
为包含 PL/SQL 块的每个 IN 或 IN OUT REF CURSOR 参数传递字符串,以打开 REF CURSOR。 此块可以执行 OPEN FOR SELECT 语句,也可以调用在 OUT 参数中返回打开的 REF CURSOR 的函数或过程。
当过程或函数返回时,对返回的 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();
}
}
}
}