4

my scenario

i'm using ODP.NET oracle provider with c# 3.5, and i am trying to pass an array as parameter for a procedure...like this:

var paramNames = new OracleParameter();
paramNames.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
paramNames.ParameterName = "P_JOB_TITLE";
paramNames.Size = 2;
paramNames.Value =  new string[2]{ "name1", "name1" };
cmd.Parameters.Add(paramNames);

when runtime code goes to paramNames.Value = new string[2]{ "name1", "name1" }; it catch with this error

"Value does not fall within the expected range"

Can anyone fix it?

ADDITIONAL INFO

Specifying OracleDbType the error is fixed, but executing give me some errors

paramNames.OracleDbType = OracleDbType.Varchar2;

"Unable to cast object of type 'System.String[]' to type 'System.IConvertible'."

my goal is to do something like this

http://aspalliance.com/621_Using_ODPNET_to_Insert_Multiple_Rows_within_a_Single_Round_Trip.3

ANOTHER PROBLEM WITH OUT PARAMETER

Inserting an out parameter like this

            paramNames = new OracleParameter();
            paramNames.ParameterName = "O_JOB_ID";
            paramNames.Size = 3;
            paramNames.Direction = ParameterDirection.Output;
            paramNames.OracleDbType = OracleDbType.Int32;
            paramNames.Value = new int[3] { 0, 0, 0 }; ;
            cmd.Parameters.Add(paramNames);

it is correctly filled when ExecuteNonQuery finished. For example the pls-sql procedure performs 3 inserts and i return the row-id of each array record.

But i something goes wrong, for example isnerting the 2nd row, the entire OUT parameters (array) are always set on 0. I expected at least the params[0].value was enhanced

Thanks

user756037
  • 285
  • 1
  • 8
  • 20

1 Answers1

5

I think you are trying to merge an Array Bind {simply binding an array to a param to have it execute multi times -- this is how the example in the link you provided did it} with an Associative Array {re: PLSQLAssociativeArray with an INPUT param of TABLE OF}.

Since you didn't post your package/proc that you are running, I am assuming you are doing something like this (just putting this down to validate the assumption)

procedure insertdata(P_JOB_TITLE IN VARCHAR2) as
begin
insert into myTable(x) value (P_JOB_TITLE);
end  insertdata;

To execute this like the author of the article you need to use ArrayBindCount (check out this link, it also has an example). This also indicates, if you have multiple parameters, it will expect an ARRAY for each one.

Now to have this executed for all the P_JOB_TITLE() that you pass in

//this was missing in your example and MUST be there to tell ODP how many array elements to expect
cmd.ArrayBindCount = 2;

 string[] jobTitleArray = {"name1", "name1"};

OracleParameter paramNames= new OracleParameter("P_JOB_TITLE", OracleDbType.Varchar2);

   //paramNames.CollectionType = OracleCollectionType.PLSQLAssociativeArray;/*once again, you are passing in an array of values to be executed and not a pl-sql table*/

    //paramNames.Size = 2; /* this is unnecessary since it is for a plsql-associative array*/
    paramNames.Value =  jobTitleArray ;
    cmd.Parameters.Add(paramNames);

For a plSQLAssociativeArray example have a look at the samples provided when you installed ODP @ %ORA_HOME%\odp.net\samples\2.x\AssocArray

and for array bind examples (as from the link you provided) @ %ORA_HOME%\odp.net\samples\2.x\ArrayBind

Harrison
  • 8,970
  • 1
  • 32
  • 28
  • ok man thanks i fixed it.....BUT now i have another problem...i introduce an OUT parameter as array and it works like a sharm BUT only WHEN the PLSQL procedure ens successfully. If during array looping something goes wrong, all the OUT array parameters are reset – user756037 Jun 20 '11 at 14:22
  • @user756037 are you doing any exception handling in the pl/sql block that is being executed? you ought to be able to capture and handle (or at least no interrupt the other items in the array) via not allowing the exception to bubble up. – Harrison Jun 20 '11 at 14:27
  • i only call cmd.ExecuteNonQuery(); in try{}catch{} statement, and in finally{} i check parameters – user756037 Jun 20 '11 at 14:35
  • @user756037 if you cannot change the procedure to encapsulate the error, you may be able to do the same via an anon. block in your C# with exception handling. e.g. 'BEGIN myProc(:myParam); exception when **** end;' – Harrison Jun 20 '11 at 14:51
  • i already implemented an exception handling in my c# function. i try {} catch {} ExecuteNonQuery() code. It catch as expected (violating my test unique key constraint for row 2) but then the OUT parameters are all bleached – user756037 Jun 20 '11 at 15:00
  • @user756037 guess I am not following you 100%, but I think this warrants a new question with code snippet to be plain as day. – Harrison Jun 20 '11 at 15:03