【问题标题】:PLS-00306: wrong number or types of arguments error in C#PLS-00306:C# 中的参数错误数量或类型错误
【发布时间】:2014-03-27 14:26:47
【问题描述】:

我们在 C# 程序中使用 Oracle 存储过程,在我们添加“v_nameurn”变量之前它工作正常。

这是 Oracle 过程:

create or replace procedure stats_By_Date (
   v_SDate   IN varchar2, 
   v_EDate   IN varchar2, 
   v_user    IN number, 
   v_nameurn IN number,
   p_cursor  OUT SYS_REFCURSOR
) as 
BEGIN
   OPEN p_cursor FOR
     select T1.Staff_No, 
            T3.Title, 
            T2.Verno, 
            To_char(T1.Response_dt, 'DD/MM/YYYY'), 
            T5.Response, 
            T6.Forenames||' '||T6.Surname
       from TOU.Users_version_link T1, 
            TOU.Version T2, 
            TOU.name T3, 
            TOU.Admin_Access T4, 
            Tou.CV_Response T5, 
            corp.wforce_employee@remote_DWLive T6
      where T1.Version_urn=T2.Urn
        and T1.Name_urn= T3.urn
        and T3.urn = T4.name_urn
        and T1.Response_urn=T5.urn
        and T1.staff_no=T6.Staff_Number
        and Trunc(T1.Response_dt) >= To_date(v_Sdate, 'DD/MM/YYYY')
        and Trunc(T1.Response_dt) <= To_date(v_EDate, 'DD/MM/YYYY')
        and T4.Staff_No = v_user
        and T3.urn = v_nameurn;
End;

这里是 C# 代码:

this.ConnectToDb();
var cmd = new OracleCommand
{
   Connection = cn,
   CommandText = "TOU.Stats_By_Date",
   CommandType = CommandType.StoredProcedure
 };
 var id = HttpContext.Current.User.Identity.Name.Split('\\')[1].ToString();
 cmd.Parameters.Add("v_SDate", OracleDbType.Varchar2).Value = 
          startdate.ToString("dd-MM-yyyy");
 cmd.Parameters.Add("v_EDate", OracleDbType.Varchar2).Value = 
          enddate.ToString("dd-MM-yyyy");
 cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
 cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;
 var rc = cmd.Parameters.Add("p_cursor", OracleDbType.RefCursor);
 rc.Direction = ParameterDirection.Output;
 cmd.ExecuteNonQuery();
 this.DisconnectFromDb(); 

请对可能出现的问题有任何建议吗?两段代码中总共有 5 个变量(4 输入,1 输出),这很好,并且所有数据类型似乎都匹配。我还尝试了实际 v_nameurn 变量的不同变体,因此我尝试了 3,“3”,并预先将其定义为 Int 变量。

【问题讨论】:

  • 对不起,如果这是一个愚蠢的问题,但你每次都关闭连接吗?
  • 谢谢,是的,我已经更新了我的代码
  • 我不确定您为什么要从 C# 以 "dd-MM-yyyy" 格式传递日期,并在 Oracle 中使用 'DD/MM/YYYY' 格式将其转换为日期。虽然这可能不是错误的原因,但对我来说似乎是错误的。您也可以尝试将 3 解析为整数,就像为 id 所做的那样,我的意思是 int.Parse(3),我不知道它在 C# 中是如何工作的,但值得一试。
  • 对不起,如果这是另一个愚蠢的问题,但是您确定您在 C# 代码所在的架构 (TOU) 中创建了新版本的存储过程(使用 v_nameurn 参数)寻找它?一种检查方法是查看 SQL*Plus 中的 DESCRIBE TOU.STATS_BY_DATE 命令是否显示新参数。
  • 另一个小建议,确保为 OracleCommand 将 BindByName 属性设置为 True,否则 Oracle 会尝试在位置上匹配参数。它可能不会影响您的错误,但这是一个很好的做法。

标签: c# oracle plsql odp.net


【解决方案1】:

Decimal is Oracle NUMBER type.. 所以更改 v_user 和 'v_nameurn' 的数据类型

cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = int.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3;

OracleDbType Enumeration

【讨论】:

  • 非常感谢,我已经更新了我的代码(和原始帖子),但不幸的是仍然遇到同样的错误。
【解决方案2】:
cmd.Parameters.Add("v_user", OracleDbType.Decimal).Value = decimal.Parse(id);
cmd.Parameters.Add("v_nameurn", OracleDbType.Decimal).Value = 3m;

处理小数时必须使用小数。对于 Oracle,小数不能很好地转换为整数,反之亦然。

【讨论】:

    【解决方案3】:

    这是证明 oracle 不是对开发人员友好的 RDBMS 的错误之一。为什么他们不能告诉你这两个问题中的哪一个是我不知道的问题。我有一个冗长的list of things to check 可以归结为以下几点:

    • 缺少逗号
    • 参数数量错误
    • 参数顺序错误,cmd.BindByName 为假
    • 使用一个参数两次,cmd.BindByName为假(如果是inline sql的情况下)
    • 参数上的数据类型匹配。为避免出现此问题,请对所有输入参数使用 .Add("paramName",value) 重载并推断类型。

    但是,从这个外观来看,我想我要在我的列表中再添加一个:确保您正在调用您认为正在调用的过程。我在程序上看到了“TOU”限定符。我必须假设这是一个模式,而不是基于 sql 脚本的包。您是否正在更改此架构中的 proc?如果您删除 .net 代码中的新参数,它会起作用还是会出现相同的错误?你应该得到同样的错误,但如果你不这样做,你可能会将新的 proc 加载到错误的架构中。

    你能做的最后一件事就是从一个 proc 的 shell 开始,一次添加一个 proc,直到你弄清楚发生了什么。

    我会说您的 int.Parse(id) 有点奇怪 - 您的经过身份验证的用户 ID 只是整数吗?但无论如何,我希望那里出现 .net 错误,而不是 oracle 错误。

    【讨论】:

      【解决方案4】:

      我在不同的情况下遇到了同样的错误。

      使用 OleDB 和更早版本的 Oracle,您无需在调用存储过程时设置返回参数:

      PROCEDURE getThingByID
      (thingID NUMBER,
      results IN OUT tSelectCursor) IS
      selectCursor tSelectCursor;
      BEGIN
      OPEN selectCursor FOR
       SELECT Name, Description, IsDeleted
       FROM thing WHERE thingID = getThingByID.thingID;
      results := selectCursor;
      END;
      

      C#/伪:

      cn = New OleDbConnection("Provider=msdaora.1;Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
      cn.Open();
      oleDBCmd = cn.CreateCommand();
      oleDBCmd.CommandType = CommandType.StoredProcedure;
      oleDBCmd.CommandText = "ThingPackage.GetThingByID";
      oleDBCmd.Parameters.Add(new OleDbParameter("thingID", "1"));
      

      我们在没有 tSelectCursor 输入输出参数的情况下执行它:

      dataReader = oleDBCmd.ExecuteReader();
      

      根据:C# and Oracle 10g database to call stored procedure

      但是,重要的是要注意,如果您使用 Oracle 12c 数据库执行此操作,则在 10g 数据库上使用 Oracle 9.2 驱动程序时会出现错误:

      “ORA-06550: PLS-00306: 调用 'GETTHINGBYID' 时参数的数量或类型错误”

      我发现你是否指定了它所期望的输出参数:

      oleDBCmd.Parameters.Add(parm);
      

      您没有收到 PLS-00306: wrong number or types of arguments in call to {proc name} 错误,但添加后您会收到:

      size 属性的大小为 0 无效

      这让我们别无选择(我不知道如何克服这个问题)求助于 Oracle Managed Data ODP.Net 驱动程序。

      ODP.Net在调用存储过程时必须设置返回参数,不像OleDB,Oracle驱动提供REFCURSOR输出参数:

      PROCEDURE getThingByID2
      (thingID NUMBER,
      results OUT SYS_REFCURSOR) IS
      BEGIN
      OPEN refCursor FOR
       SELECT Name, Description, IsDeleted
       FROM thing WHERE thingID = getThingByID2.thingID;
      END;
      

      现在我们可以很容易地调用它:

      ocn = New OracleConnection("Data Source=myTNSEntry;User ID=fakeuser;Password=abc123");
      ocn.Open();
      ocmd = ocn.CreateCommand();
      ocmd.CommandType = CommandType.StoredProcedure();
      ocmd.CommandText = "ThingPackage.GetThingByID2";
      ocmd.Parameters.Add(New OracleParameter("thingID", "1"));
      ocmd.Parameters.Add(New OracleParameter("results", OracleDbType.RefCursor, ParameterDirection.InputOutput));
      
      dataReader = ocmd.ExecuteReader();
      

      对于使用 SSL,您可能会遇到 .Net Oracle SSL 钱包问题'网络传输:解析钱包位置时 SSL 失败': Oracle.ManagedDataAccess to AWS RDS DB - TCPS: Invalid SSL Wallet (Magic)

      【讨论】:

        猜你喜欢
        • 2015-09-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多