ORA-06550 and PLS-00306 Errors When Calling Stored Procedure with UDT Table Parameter using ODP.NET on .NET 6

39 views Asked by At

I am currently developing an application using ODP.NET on .NET 6, and I've encountered an issue when trying to call a stored procedure that takes a user-defined type (UDT) table as a parameter. The Oracle database version I am working with is 11g.

The specific error message I receive is as follows:

ORA-06550: line 1, column 13:
PLS-00306: wrong number or types of arguments in call to 'GET_TYPE_SHAPE'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

This error occurs when I attempt to invoke the stored procedure, which is designed to accept a UDT table parameter. I've ensured that the UDT is correctly defined and matches the expected structure in the database. However, the call to the stored procedure seems to be failing due to an issue related to the UDT parameter handling.

When I switched to version 19c, I didn't have this error and worked normally. This is my code:

Oracle sql

CREATE TABLE target_table (
    column1 NUMBER,
    column2 VARCHAR2(50),
    column3 DATE
);
CREATE OR REPLACE TYPE my_object AS OBJECT (
    column1 NUMBER,
    column2 VARCHAR2(50),
    column3 DATE
);
CREATE OR REPLACE TYPE my_table AS TABLE OF my_object;
CREATE OR REPLACE PROCEDURE my_procedure (
    p_my_table IN my_table
) AS
BEGIN
    FOR i IN 1 .. p_my_table.COUNT LOOP
        INSERT INTO target_table (column1, column2, column3)
        VALUES (p_my_table(i).column1, p_my_table(i).column2, p_my_table(i).column3);
    END LOOP;
END;

C#

 [OracleCustomTypeMapping("myschema.MY_OBJECT")]
 public class MyObject : IOracleCustomType, INullable
    {
        private bool isNull;
        public bool IsNull => isNull;

        [OracleObjectMapping("COLUMN1")]
        public decimal Column1 { get; set; }

        [OracleObjectMapping("COLUMN2")]
        public string Column2 { get; set; }

        [OracleObjectMapping("COLUMN3")]
        public DateTime Column3 { get; set; }

        public static MyObject Null => new MyObject { isNull = true };

        public void FromCustomObject(OracleConnection con, object udt)
        {
            OracleUdt.SetValue(con, udt, "COLUMN1", Column1);
            OracleUdt.SetValue(con, udt, "COLUMN2", Column2);
            OracleUdt.SetValue(con, udt, "COLUMN3", Column3);
        }

        public void ToCustomObject(OracleConnection con, object udt)
        {
            Column1 = (decimal)OracleUdt.GetValue(con, udt, "COLUMN1");
            Column2 = (string)OracleUdt.GetValue(con, udt, "COLUMN2");
            Column3 = (DateTime)OracleUdt.GetValue(con, udt, "COLUMN3");
        }
    }



public class MyTable : IOracleCustomType
    {
        [OracleArrayMapping()]
        public MyObject[] MyObjects { get; set; }

        public void FromCustomObject(OracleConnection con, object udt)
            => OracleUdt.SetValue(con, udt, 0, MyObjects);

        public void ToCustomObject(OracleConnection con, object udt)
            => MyObjects = (MyObject[])OracleUdt.GetValue(con, udt, 0);

        public MyTable(MyObject[] myObjects)
            => MyObjects = myObjects;

        public MyTable() { }
    }

    [OracleCustomTypeMapping("myschema.MY_TABLE")]
    public class MyTableFactory : IOracleArrayTypeFactory
    {

        public Array CreateArray(int numElems)
        {
            return new MyObject[numElems];
        }

        public Array CreateStatusArray(int numElems)
        {
            return null;
        }
    }

Code to call sp

string connectionString = "my oracle 11g connection string";
MyObject[] myObjectsArray = new MyObject[2];
myObjectsArray[0] = new MyObject { Column1 = 123, Column2 = "Test 1", Column3 = DateTime.Now };
myObjectsArray[1] = new MyObject { Column1 = 456, Column2 = "Test 2", Column3 = DateTime.Now };
using (OracleConnection connection = new OracleConnection(connectionString))
{
    connection.Open();

    using (OracleCommand command = new OracleCommand("my_procedure", connection))
    {
        command.CommandType = CommandType.StoredProcedure;

        OracleParameter param = new OracleParameter();
        param.ParameterName   = "p_my_table";
        param.OracleDbType    = OracleDbType.Array;
        param.Direction       = ParameterDirection.Input;
        param.UdtTypeName     = "myschema.MY_TABLE";
        param.Value           = new MyTable(myObjectsArray);

        command.Parameters.Add(param);

        command.ExecuteNonQuery();
    }
}

I am seeking advice or solutions from anyone who has faced a similar issue or has expertise in working with UDTs and stored procedures in ODP.NET, especially in the context of .NET 6 and Oracle 11g. Any insights into how to resolve the ORA-06550 and PLS-00306 errors would be greatly appreciated.

Thank you in advance for your assistance and suggestions.

0

There are 0 answers