【问题标题】:How to call an Oracle function with a Ref Cursor as Out-parameter from C#?如何使用 Ref Cursor 作为 C# 的 Out-parameter 调用 Oracle 函数?
【发布时间】:2011-06-15 15:29:01
【问题描述】:

我正在使用一种产品,该产品提供基于 Oracle 函数的数据库 API,并且我通常能够通过 ODP.NET 调用函数。但是,我不知道如何调用包含 Ref Cursor 作为 Out 参数的函数。到目前为止,我发现的所有示例要么调用具有 Out 参数的过程,要么调用具有 Ref Cursor 作为返回值的函数。我尝试类似地定义参数,但不断收到错误,即提供了错误数量或类型的参数。

这是函数头(显然是混淆的):

FUNCTION GetXYZ(
   uniqueId       IN   somepackage.Number_Type,
   resultItems    OUT  somepackage.Ref_Type)
   RETURN somepackage.Error_Type;

这些是“somepackage”中的类型定义:

SUBTYPE Number_Type IS NUMBER(13);
TYPE Ref_Type IS REF CURSOR;
SUBTYPE Error_Type IS NUMBER;

这是我尝试过的代码:

string sql = "otherpackage.GetXYZ";
var getXYZCmd = OracleCommand oracleConnection.CreateCommand(sql);
getXYZCmd.CommandType = CommandType.StoredProcedure;

getXYZCmd.Parameters.Add("uniqueId", OracleDbType.Int32).Value = uniqueExplosionId;
getXYZCmd.Parameters.Add("resultItems", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
getXYZCmd.Parameters.Add("return_value", OracleDbType.Int32).Direction = ParameterDirection.ReturnValue;

我尝试了以下不同的方式来调用该函数(当然一次只有一种):

var result = getXYZCmd.ExecuteNonQuery();
var reader = getXYZCmd.ExecuteReader();
var scalarResult = getXYZCmd.ExecuteScalar();

但是它们每个都失败并显示错误消息:

Oracle.DataAccess.Client.OracleException: ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored.

那么通常是否可以使用 ODP.NET 从 C# 调用具有 Ref Cursor 作为 Out-parameter 的函数?我可以使用 Varchar2-Out 参数而不是 Ref Cursor 调用具有相同结构的函数,而不会出现问题...

顺便说一句,我在 Visual Studio 2008 中使用 C#.NET 3.5 的 ODP.NET 版本 2.112.2.0。

提前感谢您的帮助!

【问题讨论】:

    标签: oracle function odp.net sys-refcursor ref-cursor


    【解决方案1】:

    你当然可以。有一些需要注意的问题,但这里有一个测试用例

    create or replace function testodpRefCursor(
                      uniqueId    IN NUMBER 
                     ,resultItems OUT NOCOPY SYS_REFCURSOR) RETURN NUMBER
                     IS
    
     BEGIN
          OPEN resultItems for select level from dual  connect by level < uniqueId ;
          return 1;
     END testodpRefCursor;
    
    1. 我发现 函数喜欢有 ReturnValue 作为THE FIRST 参数 在集合中
    2. BindByName 默认为 FALSE,因此默认为 BIND BY POSITION

    否则就很直接了:

      OracleCommand cmd = new OracleCommand("TESTODPREFCURSOR", con);
      cmd.CommandType   = CommandType.StoredProcedure;
      cmd.BindByName = true;
      // Bind 
    
    
      OracleParameter oparam = cmd.Parameters.Add("ReturnValue", OracleDbType.Int64);
      oparam.Direction = ParameterDirection.ReturnValue ;       
    
      OracleParameter oparam0 = cmd.Parameters.Add("uniqueId", OracleDbType.Int64);
      oparam0.Value = 5 ;
      oparam0.Direction = ParameterDirection.Input;
    
      OracleParameter oparam1 = cmd.Parameters.Add("resultItems", OracleDbType.RefCursor);
      oparam1.Direction = ParameterDirection.Output;
    
    
    
    
      // Execute command
      OracleDataReader reader;
      try
      {
        reader = cmd.ExecuteReader();
    
        while(reader.Read() ){
            Console.WriteLine("level: {0}", reader.GetDecimal(0));  
        }
    
      } ...
    

    现在要获取更多示例,请转到您的 Oracle 主目录并查看 @ODP.NET 中的 Ref 游标示例

    例如: %oracle 客户端首页%\odp.net\samples\4\RefCursor

    【讨论】:

    • 感谢您提供示例目录。你拯救了这一天:]
    猜你喜欢
    • 2021-01-08
    • 1970-01-01
    • 2011-10-24
    • 2012-07-01
    • 1970-01-01
    • 2017-03-19
    • 2018-08-15
    • 2020-05-05
    • 1970-01-01
    相关资源
    最近更新 更多