1

我有一个至少有 30 个参数的存储过程。大多数情况下都指定了默认值,没有指定默认值的被认为是强制性的。

以下通过 SQL plus 执行时对我有用。

DECLARE
l_error_value NUMBER;
l_error_product VARCHAR2(10);
l_ce_doc_id NUMBER;
BEGIN
procedurename
( ce_cat => 'RO'
, ce_class => 'REP'
, ce_location => location value'
, ce_description => 'description value'
, ce_enquiry_type => 'IR'
, ce_source => 'W'
, ce_incident_datetime => '01-JAN-2014'
, ce_doc_outcome =>'FC'
, ce_doc_outcome_reason => 'First Contact'
, ce_doc_id => l_ce_doc_id
, error_value => l_error_value
, error_product => l_error_product
);
END;
/

大多数是 Varchar2,除了日期时间(日期时间)、ce_doc_id 是数字和 error_product 是数字。

当我尝试将它与 asp.net 和 oracle.dataaccess 组件一起使用时,它始终给我:

PLS-00306:调用“PROCEDURE NAME”时参数的数量或类型错误。

现在开车有点疯狂。

以下是我的(尽管代码很乱)。

 using (OracleConnection connection = new OracleConnection(oracleconnection.thisConnString()))
            {
                connection.Open();

                OracleCommand command = new OracleCommand(procedureName, connection);
                command.CommandType = CommandType.StoredProcedure;


                OracleParameter thisParam = new OracleParameter();
                thisParam.Direction = ParameterDirection.Input;
                thisParam.OracleDbType = OracleDbType.Varchar2;
                thisParam.Value = "RO";
                thisParam.ParameterName = "ce_cat";
                OracleParameter thisParam2 = new OracleParameter();
                thisParam2.Direction = ParameterDirection.Input;
                thisParam2.OracleDbType = OracleDbType.Varchar2;
                thisParam2.Value = "REP";
                thisParam2.ParameterName = "ce_class";
                OracleParameter thisParam3 = new OracleParameter();
                thisParam3.Direction = ParameterDirection.Input;
                thisParam3.OracleDbType = OracleDbType.Varchar2;
                thisParam3.Value = "Location";
                thisParam3.ParameterName = "ce_location";
                OracleParameter thisParam4 = new OracleParameter();
                thisParam4.Direction = ParameterDirection.Input;
                thisParam4.OracleDbType = OracleDbType.Varchar2;
                thisParam4.Value = "Description";
                thisParam4.ParameterName = "ce_description";
                OracleParameter thisParam5 = new OracleParameter();
                thisParam5.Direction = ParameterDirection.Input;
                thisParam5.OracleDbType = OracleDbType.Varchar2;
                thisParam5.Value = "IR";
                thisParam5.ParameterName = "ce_enquiry_type";
                OracleParameter thisParam6 = new OracleParameter();
                thisParam6.Direction = ParameterDirection.Input;
                thisParam6.OracleDbType = OracleDbType.Varchar2;
                thisParam6.Value = "W";
                thisParam6.ParameterName = "ce_source";
                OracleParameter thisParam7 = new OracleParameter();
                thisParam7.Direction = ParameterDirection.Input;
                thisParam7.OracleDbType = OracleDbType.Date;
                thisParam7.Value = DateTime.Now;
                thisParam7.ParameterName = "ce_incident_datetime";
                OracleParameter thisParam8 = new OracleParameter();
                thisParam8.Direction = ParameterDirection.Input;
                thisParam8.OracleDbType = OracleDbType.Varchar2;
                thisParam8.Value = "FC";
                thisParam8.ParameterName = "ce_doc_outcome";
                OracleParameter thisParam9 = new OracleParameter();
                thisParam9.Direction = ParameterDirection.Input;
                thisParam9.OracleDbType = OracleDbType.Varchar2;
                thisParam9.Value = "First Contact";
                thisParam9.ParameterName = "ce_doc_outcome_reason";

                OracleParameter thisParam10 = new OracleParameter();
                thisParam10.Direction = ParameterDirection.ReturnValue;
                thisParam10.OracleDbType = OracleDbType.Decimal;
                thisParam10.ParameterName = "ce_doc_id";
                OracleParameter thisParam11 = new OracleParameter();
                thisParam11.Direction = ParameterDirection.ReturnValue;
                thisParam11.OracleDbType = OracleDbType.Varchar2;
                thisParam11.ParameterName = "error_value";
                OracleParameter thisParam12 = new OracleParameter();
                thisParam12.Direction = ParameterDirection.ReturnValue;
                thisParam12.OracleDbType = OracleDbType.Decimal;
                thisParam12.ParameterName = "error_product";

                command.Parameters.Add(thisParam);
                command.Parameters.Add(thisParam2);
                command.Parameters.Add(thisParam3);
                command.Parameters.Add(thisParam4);
                command.Parameters.Add(thisParam5);
                command.Parameters.Add(thisParam6);
                command.Parameters.Add(thisParam7);
                command.Parameters.Add(thisParam8);
                command.Parameters.Add(thisParam9);
                command.Parameters.Add(thisParam10);
                command.Parameters.Add(thisParam11);
                command.Parameters.Add(thisParam12);


                command.ExecuteNonQuery();


            }

在上一个版本(如已发布)中,我用 returnvalue 替换了输出,看看它是否有任何区别 - 没有。

我是否遗漏了什么,或者因为我使用的是 asp.net 和 oracle odac,我是否需要指定所有参数,即使是那些具有默认值的参数?

4

2 回答 2

0

我发现调试这些类型问题的最佳方法是在 C# 代码和存储过程中注释掉除一个参数之外的所有参数。编译它并确保它有效。然后取消注释掉 10 个参数,重新编译并查看是否有效。继续以 10 个为一组执行此操作,直到代码中断。然后您知道它是您刚刚添加的 10 个之一,因此您可以开始一个一个添加,直到找到破坏您的代码的那个。

我将这种技术称为“二进制搜索调试”。:)

此外,如果您将 30 个参数传递给 SP,您可能想看看是否可以以某种方式简化该过程。正如您所发现的,有了这么多参数,事情可能会变得有点笨拙。

于 2014-02-10T19:53:44.677 回答
0

我通过 ODP.NET 打开了跟踪,以查看它在 SQL 方面生成了什么。似乎 ODP.NET 对 date > OracleDbType.Date 转换和输入它的值很有趣。

于 2014-02-12T17:28:36.773 回答