0

从下面的给定信息中寻找一些帮助来识别调用 Oracle 过程调用的正确方法。我将 .NET 4 与 Oracle.DataAccess.Client 一起使用。以下是 Oracle 程序的详细信息:

CREATE OR REPLACE PACKAGE APPS.syk_serial_num_details
AS
TYPE account_rec_type IS RECORD(
  inv_item_id                   NUMBER
 ,item_num                      VARCHAR2(40)
 ,item_desc                     VARCHAR2(240)
 ,acc_num                       VARCHAR2(30)
 ,ship_to                       VARCHAR2(1000)
 ,bill_to                       VARCHAR2(1000)
);

TYPE account_set IS TABLE OF account_rec_type; 

 PROCEDURE get_prod_details(
  p_serial_num               IN       VARCHAR2
 ,p_acc_nums                 IN       VARCHAR2
 ,p_ship_tos                 IN       VARCHAR2
 ,p_acc_set                  OUT      syk_serial_num_details.account_set
 ,p_status                   OUT      VARCHAR2
 );

END syk_serial_num_details

以下是显示参数类型和大小的更多详细信息……下面是从 Toad 接口调用过程的示例:

DECLARE
l_serial_num                  csi_item_instances.serial_number%type;
l_acc_nums                    VARCHAR2(100);
l_ship_tos                    VARCHAR2(100);
l_acc_set  syk_serial_num_details.account_set;
l_status                      VARCHAR2(80);

BEGIN

   l_serial_num               :=  '1025200453';
   l_acc_nums                 := '8165';
   l_ship_tos                 := '10332';
   l_acc_set := syk_serial_num_details.account_set();
   syk_serial_num_details.get_prod_details(p_serial_num                  => l_serial_num
                                          ,p_acc_nums                    => l_acc_nums
                                          ,p_ship_tos                    => l_ship_tos
                                          ,p_acc_set                     => l_acc_set
                                          ,p_status                      => l_status
                                          );


   Dbms_output.put_line('Status ::' || l_status);
   IF(l_acc_set.count >0) then
   FOR i IN 1 .. l_acc_set.count
   LOOP
   l_acc_set.extend;
      DBMS_OUTPUT.put_line(   'Item_Number:'
                           || l_acc_set(i).item_num||'|'
                           || '   Desc:'
                           || l_acc_set(i).item_desc||'|'
                           || '   Accunt Number:'
                           || l_acc_set(i).acc_num||'|'
                           || '   Ship To:'
                           || l_acc_set(i).ship_to||'|'
                           || '   Bill To:'
                           || l_acc_set(i).bill_to||'|'
                          );
   END LOOP;
   end if;

END;

所以...我在尝试确定 p_acc_set 输出的正确类型时遇到了很多麻烦。以下是我当前的 C# 代码:

        OracleConnection conn = getOracleConnection();
        List<AccountSearchResultsDto> ProductInfoList = new List<AccountSearchResultsDto>();
        using (conn)
        {
            conn.Open();

            using (OracleCommand cmd = new OracleCommand("syk_serial_num_details.get_prod_details", conn))
            {

                cmd.CommandType = CommandType.StoredProcedure;

                //ASSIGN PARAMETERS TO BE PASSED 
                OracleParameter param1 = new OracleParameter("p_serial_num", OracleDbType.Varchar2);
                param1.Direction = ParameterDirection.Input;
                param1.Size = 100;
                param1.Value = "1025200453";
                cmd.Parameters.Add(param1);

                OracleParameter param2 = new OracleParameter("p_acc_nums", OracleDbType.Varchar2);
                param2.Direction = ParameterDirection.Input;
                param2.Size = 100;
                param2.Value = "8165";
                cmd.Parameters.Add(param2);

                OracleParameter param3 = new OracleParameter("p_ship_tos", OracleDbType.Varchar2);
                param3.Direction = ParameterDirection.Input;
                param3.Size = 100;
                param3.Value = "10332";
                cmd.Parameters.Add(param3); 


                //PARAMETERS USED TO RETURN RESULT OF PROCEDURE CALL 
                OracleParameter param4 = new OracleParameter("p_acc_set", OracleDbType.Object);
                param4.Direction = ParameterDirection.Output;
                param4.Size = 1;
                cmd.Parameters.Add(param4);

                OracleParameter param5 = new OracleParameter("p_status", OracleDbType.Varchar2);
                param5.Direction = ParameterDirection.Output;
                param5.Size = 300;
                cmd.Parameters.Add(param5); 


                cmd.ExecuteNonQuery();

                if (cmd.Parameters["p_status"].Value.ToString().Equals("SUCCESS"))
                {
                       //Get results from p_acct_set and put values in list
                }



            }
        }

截至目前 - 尝试上述我收到以下错误:

无效的参数绑定参数名称:p_acc_set

我应该为 p_acc_set 使用 OracleParameter UdtTypeName 参考吗?

我对 Oracle 过程调用很陌生,所以请原谅我的经验不足。任何帮助表示赞赏!提前致谢!!

-R

4

2 回答 2

0

OracleCommand 类的属性BindByName默认为 false)来处理这个问题。

您应该在执行命令之前将其设置为 true以避免该错误!

欲了解更多信息,请阅读内容!!

编辑

抱歉,我没有注意到有一个 PL/SQL 嵌套表!!我不认为 Oracle 支持绑定(特别是如果它包含记录而不是简单值)。

关联数组、PL/SQL 嵌套表和 PL/SQL Vararrays 是非常相似的数据类型,所以在这里他们可能打算使用名称关联数组来表示所有这三个东西。

使用用户定义类型的嵌套表代替它应该可以解决您的问题,但是对于新手来说处理起来将变得非常简单......如果是这样,您应该重新定义过程以使用新的数据类型并在 C# 中设置 UdtTypeName 参数代码不是唯一要做的事情。

于 2012-07-14T18:03:21.153 回答
0

我发现参数“p_acc_set”和“p_status”与其他参数的不同之处在于他们没有为它们分配大小,请尝试为它们分配大小,应该可以解决您的问题

我没有找到MSDN对 OracleParamter.Size 属性的解释非常清楚。但我确实注意到评论中有一句话说

该行取自 MSDN 备注:

对于双向和输出参数以及返回值,您必须设置 Size 的值。

于 2012-07-14T01:42:11.867 回答