C#Oracle过程调用问题
在以下给定信息中查找有关确定调用Oracle过程调用的正确方法的帮助。我正在Oracle.DataAccess.Client中使用.NET 4。 以下是Oracle提供的该过程的详细信息:C#Oracle过程调用问题,c#,oracle,.net-4.0,C#,Oracle,.net 4.0,在以下给定信息中查找有关确定调用Oracle过程调用的正确方法的帮助。我正在Oracle.DataAccess.Client中使用.NET 4。 以下是Oracle提供的该过程的详细信息: CREATE OR REPLACE PACKAGE APPS.syk_serial_num_details AS TYPE account_rec_type IS RECORD( inv_item_id NUMBER ,item_num
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_集合输出的正确类型时遇到了很多麻烦。
以下是我目前的C#代码:
OracleConnection conn=getOracleConnection();
List ProductInfoList=新列表();
使用(康涅狄格州)
{
conn.Open();
使用(OracleCommand cmd=new OracleCommand(“syk\u serial\u num\u details.get\u prod\u details”,conn))
{
cmd.CommandType=CommandType.storedProcess;
//分配要传递的参数
OracleParameter param1=新的OracleParameter(“p_serial_num”,OracleDbType.Varchar2);
param1.Direction=ParameterDirection.Input;
参数1.尺寸=100;
param1.Value=“1025200453”;
cmd.Parameters.Add(param1);
OracleParameter param2=新的OracleParameter(“p_acc_nums”,OracleDbType.Varchar2);
param2.Direction=ParameterDirection.Input;
参数2.尺寸=100;
param2.Value=“8165”;
cmd.Parameters.Add(param2);
OracleParameter param3=新的OracleParameter(“p_ship_tos”,OracleDbType.Varchar2);
param3.Direction=ParameterDirection.Input;
参数3.尺寸=100;
param3.Value=“10332”;
cmd.Parameters.Add(param3);
//用于返回过程调用结果的参数
OracleParameter param4=新的OracleParameter(“p_acc_set”,OracleDbType.Object);
param4.Direction=ParameterDirection.Output;
参数4.尺寸=1;
cmd.Parameters.Add(param4);
OracleParameter param5=新的OracleParameter(“p_状态”,OracleDbType.Varchar2);
param5.Direction=ParameterDirection.Output;
参数5.尺寸=300;
cmd.Parameters.Add(param5);
cmd.ExecuteNonQuery();
if(cmd.Parameters[“p_status”].Value.ToString().Equals(“SUCCESS”))
{
//从p_acct_集合中获取结果,并将值放入列表中
}
}
}
到目前为止-尝试上述操作时,我得到以下错误:
无效的参数绑定
参数名称:p_acc_set
我应该为p_acc_集合使用OracleParameter UdtTypeName引用吗
我对Oracle过程调用非常陌生,请原谅我的经验不足。
感谢您的帮助!提前谢谢
-R我发现参数“p_acc_set”和“p_status”与其他参数相比的不同之处在于,它们没有为它们指定大小。请尝试为它们指定大小,并应解决您的问题 我没有在OracleParameter.Size属性上找到非常清楚的解释。但我注意到评论中有一句话说 该行取自MSDN备注: 对于双向和输出参数以及返回值,必须 设置大小的值 OracleCommand类的属性(默认为false)可以处理此问题 您应该在执行命令之前将其设置为true,以避免该错误 欲了解更多信息,请阅读 编辑 对不起,我没有注意到有一个PL/SQL嵌套表!!我认为Oracle不支持绑定(特别是当它包含记录而不是简单值时) 关联数组、PL/SQL嵌套表和PL/SQL vararray是非常相似的数据类型,因此它们可能打算将这三种类型都命名为关联数组
使用用户定义类型的嵌套表来代替它应该可以解决您的问题,但对于新手来说,这将变得非常简单……如果是这样,您应该重新定义使用新数据类型的过程,并在C代码中设置UdtTypeName参数并不是唯一要做的事情。否。请阅读OP并查看SP。@AVD您的权利我有更新了我的答案并感谢您的更正在我看来,您向名为GET_PROD_DETAILS的存储过程传递了错误数量或类型的参数。你应该单独提出这个问题mate@RustyMorton我没有粗鲁,我只是想保留评论线索smallerok,正要提出一个新问题,然后我意识到我应用大小的方式有问题。我解决了这个问题,但仍然会遇到同样的错误。我更新了代码以反映添加的size attributetried设置cmd.BindByName=true;仍然收到相同的错误“无效的参数绑定参数名称:p_acc_set”我编辑了我的答案,我认为错误消息指的是一个更简单的问题。@Allessandro感谢您的澄清。我可能会影响Oracle团队修改过程调用,使其在web前端变得更容易。除非其他人在接下来的几天内提出更好的解决方案,否则我将尝试这种方法,并让他们将记录类型更改为UDT表。
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
}
}
}