如何使用Ref Cursor作为C#的Out-parameter调用Oracle函数?

时间:2011-06-15 15:29:01

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

我正在使用提供基于Oracle功能的数据库API的产品,我通常可以通过ODP.NET调用函数。但是,我无法弄清楚,如何调用包含Ref Cursor作为Out-parameter的函数。到目前为止我找到的所有样本都调用带有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.

通常可以用CDP和ODP.NET调用带有Ref Cursor作为Out-parameter的函数吗?我可以使用Varchar2-Out参数调用具有相同结构的函数而不是Ref Cursor而没有问题...

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

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:10)

你确定可以。有一些问题需要警惕,但这是一个测试用例

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 param 在集合
  2. BindByName默认为FALSE,因此默认为BIND BY POSITION
  3. 否则它很直接:

      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

    HTH