首页 > 解决方案 > 使用用户定义类型从 .net 调用 oracle 存储过程时出现问题

问题描述

我正在尝试调用在 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 类型设置为输出参数的有用信息。

请问有人可以帮我解决这个问题吗?

标签: c#.netoraclestored-proceduresuser-defined-types

解决方案


我认为问题在于您的输出类型不是 Varchar2,正如您在此行中定义的那样:

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

您已p_system_details定义为 varchar2s 和日期的对象,而不是单个 varchar2。返回类型可能Array取决于您使用的 Oracle 数据访问驱动程序。例如,此解决方案Array对其 UDT 使用返回类型。

如果您的驱动程序没有正确支持 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);

推荐阅读