Search code examples
c#odp.netoracle-xeuser-defined-types

Invalid binding for Oracle UDT in procedure parameter


I'm attempting to call a procedure that takes a custom data type of table of numbers as one of the parameters.

Here is the definition of the type:

create type num_list as table of number;

And the definition of the procedure:

create or replace procedure my_procedure
    (listofnumbers num_list,
                  v_value char)
is
begin

  update my_table
     set my_column = v_value
   where my_row_id in (select column_value
                         from table(listofnumbers));

end;

Using ODP.NET and C#, I'm declaring it as follows:

var row_ids = new int[] { 1, 2 };

using (var oracleConn = new Oracle.DataAccess.Client.OracleConnection(myConnectionString))
{
    oracleConn.Open();
    var cmd = new Oracle.DataAccess.Client.OracleCommand("my_procedure", oracleConn);
    cmd.CommandType = CommandType.StoredProcedure;

    var param1 = new Oracle.DataAccess.Client.OracleParameter("listofnumbers", Oracle.DataAccess.Client.OracleDbType.Array, ParameterDirection.Input);
    param1.CollectionType = Oracle.DataAccess.Client.OracleCollectionType.PLSQLAssociativeArray;
    param1.UdtTypeName = "num_list";
    param1.Value = row_ids;
    cmd.Parameters.Add(param1);

    var param2 = new Oracle.DataAccess.Client.OracleParameter("v_value ", Oracle.DataAccess.Client.OracleDbType.Char, ParameterDirection.Input);
    param2.Value = "Y";
    cmd.Parameters.Add(param2);

    cmd.ExecuteNonQuery();
}

The exception being thrown states:

Invalid parameter binding Parameter name: listofnumbers

What properties am I missing in defining the parameter?


Solution

  • EDIT: May 14

    As my answer got unaccepted, here is a link that might be of use:

    http://developergeeks.com/article/35/working-with-user-defined-type-oracle-udt-and-custom-type-using-odp-net-11g


    Unfortunately I cannot play around with this as I have x64 ODP.NET which does not support UDT.

    However, as your UDT is a collection did you try setting the Size property on param1?

    param1.Size = row_ids.Length;
    

    Now, it is not a UDT, but here is a code snippet how I bind to a type defined in a package spec as:

    TYPE t_stringlist IS TABLE OF VARCHAR2(4000);
    
    
                string[] values = new string[] { "AAA", "BBB" };
    
                OracleParameter parameter = new OracleParameter();
                parameter.Name = "my_param";
                parameter.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
                parameter.OracleDbType = OracleDbType.Varchar2;
                parameter.ArrayBindSize = new int[values.Length];
                parameter.ArrayBindStatus = new OracleParameterStatus[values.Length];
                parameter.Size = values.Length;
    
                for (int i = 0; i < values.Length; ++i)
                {
                    parameter.ArrayBindSize[i] = 4000;
                    parameter.ArrayBindStatus[i] = OracleParameterStatus.Success;
                }
    
                parameter.Value = values;
    

    I am not sure what values you might set ArrayBindSize to.

    Also, you might consider creating a type factory for your UDT:

    http://download.oracle.com/docs/html/E15167_01/featUDTs.htm

    Anyway, I hope you find something here that helps.