使用用户定义的类型从.net调用oracle存储过程时出现问题

时间:2018-09-09 15:00:10

标签: c# .net oracle stored-procedures user-defined-types

我正在尝试调用Orracle软件包中定义的Oracle存储过程。 该过程没有输入参数,只有用户定义类型的输出参数。以下是该软件包和UDT的详细信息:

CREATE OR REPLACE TYPE obj_systemdetail AS OBJECT
(
          sys_id VARCHAR2(8 CHAR),
          sys_name VARCHAR2(6 CHAR),
          sys_desc VARCHAR2(100 CHAR),
          sys_start_date DATE
);

CREATE OR REPLACE TYPE tab_systemdetailslist IS TABLE OF obj_systemdetail

CREATE OR REPLACE PACKAGE pck_sysDetails IS

    PROCEDURE get_systemdetails(p_system_details OUT NOCOPY tab_systemdetailslist);

END pck_sysDetails;

尝试从.net如下调用

using Oracle.ManagedDataAccess.Client;

    OracleConnection conn = new OracleConnection("User Id=ptTest;Password=p1_sttest;Data Source=STMP231");
    OracleCommand cmd = conn.CreateCommand();
    cmd.CommandText = "pck_sysDetails.get_systemdetails";
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.Add(new OracleParameter("p_system_details", OracleDbType.Varchar2)
        {
            UdtTypeName = "tab_systemdetailslist",
            Size = 100,
            ArrayBindSize = new int[100],
            Direction = ParameterDirection.Output
        });
    conn.Open();
    cmd.ExecuteNonQuery();

能够连接到数据库,但是在执行代码时出现此错误

  

ORA-06550:“ GET_SYSTEMDETAILS”调用中参数的数量或类型错误

尝试了很多搜索,但是找不到任何有关如何将此UDT类型设置为输出参数的有用信息。

请问有人可以帮我吗?

1 个答案:

答案 0 :(得分:0)

我认为问题在于您的输出类型不是Varchar2(如您在此行中所定义):

cmd.Parameters.Add(new OracleParameter("p_system_details", OracleDbType.Varchar2)

您已将p_system_details定义为varchar2s和日期的对象,而不是单个varchar2。返回类型可能是Array,具体取决于您使用的Oracle数据访问驱动程序。例如,this solution对他们的UDT使用Array的返回类型。

如果您的驱动程序不正确地支持UDT作为类型,我认为一种选择是将存储过程的返回类型更改为驱动程序支持的某种类型,例如Oracle SYS_REFCURSOR,在.NET中定义为OracleDbType.RefCursor可以返回您要查找的相同数据元素。

create or replace PROCEDURE AOF_JOE_TEST_CURSOR_SP (p_system_details OUT SYS_REFCURSOR) AS

BEGIN
OPEN p_system_details FOR

SELECT
    'Test1' as sys_id,
    'Test2' as sys_name,
    'Test3' as sys_desc,
    SYSDATE as sys_start_date
FROM DUAL;

END;

然后,您的参数在.NET中定义为:

OracleParameter cursorParameter = new OracleParameter();
cursorParameter.ParameterName = "p_system_details";
cursorParameter.Direction = ParameterDirection.Output;
cursorParameter.OracleDbType = OracleDbType.RefCursor;
cmd.Parameters.Add(cursorParameter);