C#Oracle过程调用问题

时间:2012-07-14 01:14:05

标签: c# oracle .net-4.0

寻找一些帮助来确定从下面给定信息调用Oracle Procedure调用的正确方法。我正在使用.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

这里有一些显示param类型和大小的详细信息......下面是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

2 个答案:

答案 0 :(得分:0)

我发现参数“p_acc_set”和“p_status”与其他参数相比的差异在于它们没有为它们分配尺寸请尝试为它们指定尺寸并应该解决您的问题

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

  

该行取自MSDN备注:

     

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

答案 1 :(得分:0)

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

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

有关更多信息,请阅读this !!

修改

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

关联数组,PL / SQL嵌套表和PL / SQL Vararray是非常相似的数据类型,所以可能here他们打算使用Associative Arrays这三个名称。

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