从 C# 执行 Oracle 存储过程 - 调用中的参数数量或类型错误

Posted

技术标签:

【中文标题】从 C# 执行 Oracle 存储过程 - 调用中的参数数量或类型错误【英文标题】:Executing Oracle stored procedure from C# - wrong number or types of arguments in call 【发布时间】:2018-06-20 14:55:58 【问题描述】:

这是我描述存储过程时的输出:

 desc procedure_name  

 VCOMPTE    VARCHAR2                 IN            
 VRESULT    REF CURSOR               OUT           
 CLIENT_NO  VARCHAR2(6)              OUT           
 ACCT_NAME  VARCHAR2(35)             OUT           
 NCG        VARCHAR2(6)              OUT           
 NCG_DESC   VARCHAR2(35)             OUT           
 AGENCE     VARCHAR2(5)              OUT           
 TEL        VARCHAR2(50)             OUT

这是我用来执行它的 C# 代码:

public void Validate(string account_num)

    OracleConnection conn = new OracleConnection(HelperClass.GetConstring());         

    OracleCommand _cmdObj = conn.CreateCommand();
    _cmdObj.CommandText = "pk_xxx.procedure_name";
    _cmdObj.CommandTimeout = 1680;
    _cmdObj.CommandType = System.Data.CommandType.StoredProcedure;

    OracleParameter para_account_num = new OracleParameter();
    para_account_num.ParameterName = "VCOMPTE"; 
    para_account_num.OracleDbType = OracleDbType.Varchar2;
    para_account_num.Direction = System.Data.ParameterDirection.Input; 
    para_account_num.Value = account_num; 
    _cmdObj.Parameters.Add(para_account_num);

    OracleParameter VRESULT = new OracleParameter();
    VRESULT.ParameterName = "VRESULT";
    VRESULT.OracleDbType = OracleDbType.RefCursor;
    VRESULT.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(VRESULT);

    OracleParameter client_no = new OracleParameter();
    client_no.ParameterName = "CLIENT_NO"; 
    client_no.OracleDbType = OracleDbType.Varchar2;
    client_no.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(client_no);

    OracleParameter acct_name = new OracleParameter();
    acct_name.ParameterName = "ACCT_NAME";
    acct_name.OracleDbType = OracleDbType.Varchar2;
    acct_name.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(acct_name);

    OracleParameter ncg = new OracleParameter();
    ncg.ParameterName = "NCG";
    ncg.OracleDbType = OracleDbType.Varchar2;
    ncg.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(ncg);

    OracleParameter tr_desc = new OracleParameter();
    tr_desc.ParameterName = "NCG_DESC";
    tr_desc.OracleDbType = OracleDbType.Varchar2;
    tr_desc.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(tr_desc);

    OracleParameter AGENCE = new OracleParameter();
    AGENCE.ParameterName = "AGENCE";
    AGENCE.OracleDbType = OracleDbType.Varchar2;
    AGENCE.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(AGENCE);

    OracleParameter TEL = new OracleParameter();
    TEL.ParameterName = "TEL";
    TEL.OracleDbType = OracleDbType.Varchar2;
    TEL.Direction = System.Data.ParameterDirection.ReturnValue;
    _cmdObj.Parameters.Add(TEL);

    try
    
        conn.Open();

        OracleDataReader reader = _cmdObj.ExecuteReader();

        while (reader.Read())
        
            //I will use the data 
        
    
    catch (Exception xc)
    
        //catch xc 
    

但我得到一个错误

调用“procedure_name”时参数的数量或类型错误。”

调试对我来说很困难,因为我无法直接访问 Oracle 数据库,而且我不确定自己做错了什么。我已经在同一个数据库中成功执行了其他存储过程。提前致谢!

【问题讨论】:

ParameterDirection.ReturnValue只能有一个参数,即函数的返回值。使用ParameterDirection.Output 但是我的过程返回行而不是单个值。所有的输出类型实际上都是字段 无论如何,它们仍然是输出参数,而不是返回值。 ParameterDirection.ReturnValue只能用于函数,不能用于没有任何返回值的过程。 我已经尝试过了,但仍然没有运气。 【参考方案1】:

ExecuteReader() 仅用于函数,不用于过程。你必须使用ExecuteNonQuery()

ExecuteNonQuery() 之后你必须读取结果,例如

_cmdObj.ExecuteNonQuery();
OracleDataReader reader = ((OracleRefCursor)VRESULT.Value).GetDataReader();

或者创建一个类似

的函数
FUNCTION function_name RETURNS SYS_REFCURSOR

 VCOMPTE    VARCHAR2                 IN            
 CLIENT_NO  VARCHAR2(6)              OUT           
 ACCT_NAME  VARCHAR2(35)             OUT           
 NCG        VARCHAR2(6)              OUT           
 NCG_DESC   VARCHAR2(35)             OUT           
 AGENCE     VARCHAR2(5)              OUT           
 TEL        VARCHAR2(50)             OUT

然后这样称呼它

OracleCommand _cmdObj = conn.CreateCommand();
_cmdObj.CommandText = "pk_xxx.procedure_name";
_cmdObj.CommandType = CommandType.StoredProcedure;

_cmdObj.Parameters.Add("res", OracleDbType.RefCursor, ParameterDirection.ReturnValue);
_cmdObj.Parameters.Add("VCOMPTE", OracleDbType.Varchar2, ParameterDirection.Input).Value = account_num;
_cmdObj.Parameters.Add("CLIENT_NO", OracleDbType.Varchar2, ParameterDirection.Output);
_cmdObj.Parameters.Add("ACCT_NAME", OracleDbType.Varchar2, ParameterDirection.Output);
...
OracleDataReader reader = _cmdObj.ExecuteReader();

也许看看Data Provider for .NET Developer's Guide

【讨论】:

以上是关于从 C# 执行 Oracle 存储过程 - 调用中的参数数量或类型错误的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 调用 Oracle 存储过程?

c# 调用Oracle存储过程 PLS-00201:必须声明标识符

c#调用oracle存储过程,返回2个值

在c#中调用oracle存储过程

oracle SQL语句中怎么样调用存储过程

ADO.Net(C#)中怎么执行Oracle的存储过程