2013-04-24 36 views
5

Mam procedurę składowaną PL/SQL, która pobiera 4 wejścia. Jednym z tych danych wejściowych jest tablica asocjacyjna (Oracle Type: Table of VARCHAR2 (1) index firmy PLS_INTEGER).C# 2010, ODP.net, wywołanie procedury przechowywanej przechodzącej tablicy

Chcę mieć program C#, który wywołuje tę procedurę składowaną z odpowiednimi wejściami, w tym tablicą asocjacyjną.

Używam ODP.net 11.2 z Visual C# 2010 Express i Oracle 11gR2.

Nie mogę znaleźć żadnych dobrych przykładów jak przekazać tablicę do procedury pl/sql z C#. Czy ktokolwiek może mi podać przykład? Po dokumentacji Oracle dokładnie daje mi błąd mówiąc: Zła liczba lub typ argumentów.

Moje C# Kod:

 OracleCommand cmd = new OracleCommand("begin sdg_test.sdg_test2(:1); end;", conn); 

     OracleParameter Param1 = cmd.Parameters.Add("1", OracleDbType.Varchar2); 

     Param1.Direction = ParameterDirection.Input; 

     Param1.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 

     Param1.Value = new string[22] { "Y", "Y", "N", "Y", "N", "Y", "Y", "Y", "Y", "Y", "N", "Y", "N", "Y", "Y", "Y", "Y", "Y", "N", "Y", "N", "Y" }; 

     Param1.Size = 22; 
     Param1.ArrayBindSize = new int[22] { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }; 

     cmd.ExecuteNonQuery(); 

     conn.Close(); 
     conn.Dispose(); 

Całe postępowanie nie jest log wiadomość. Po prostu próbuję uruchomić tę koncepcję.

Odpowiedz

4

Można zacząć od (prostszy sposób):

List<int> idList = yourObjectList; 
List<int> nameList = yourObjectList; 

using (OracleConnection oraconn = new OracleConnection()) 
{ 
    oraconn.ConnectionString = "Your_Connection_string"; 

    using (OracleCommand oracmd = new OracleCommand()) 
    { 
     oracmd.Connection = oraconn; 

     oracmd.CommandType = CommandType.StoredProcedure; 
     oracmd.CommandText = "Your_Procedura_name"; 
     oraconn.Open(); 

     // To use ArrayBinding, you need to set ArrayBindCount 
     oracmd.BindByName = true; 
     oracmd.ArrayBindCount = idList.Count; 

     // Instead of single values, we pass arrays of values as parameters 
     oracmd.Parameters.Add("ids", OracleDbType.Int32, oyourObjectList.ToArray(), ParameterDirection.Input); 
     oracmd.Parameters.Add("names", OracleDbType.Varchar2, oyourObjectList.ToArray(), ParameterDirection.Input); 

     oracmd.ExecuteNonQuery(); 
     oraconn.Close(); 
    } 
} 

Następnie dodać pakiet/procedurę w dB:

PROCEDURE Your_Procedure_name(
     name IN VARCHAR2, 
     id IN NUMBER 
    ) IS  
BEGIN 

    INSERT INTO your_table VALUES(id, name); 
END Your_Procedure_name; 

Inną opcją jest:

using (OracleConnection oraconn = new OracleConnection()) 
{ 
    oraconn.ConnectionString = "Your_Connection_string"; 

    using (OracleCommand cmd = new OracleCommand()) 
    { 

     cmd.Connection = oraconn; 

     cmd.CommandType = CommandType.StoredProcedure; 
     cmd.CommandText = "Your_Procedure_name"; 
     oraconn.Open(); 


     OracleParameter idParam = new OracleParameter("i_idList", OracleDbType.Int32, ParameterDirection.Input); 
     idParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
     idParam.Value = idList.ToArray(); 
     idParam.Size = idList.Count; 

     OracleParameter nameParam = new OracleParameter("i_nameList", OracleDbType.Varchar2, ParameterDirection.Input); 
     nameParam.CollectionType = OracleCollectionType.PLSQLAssociativeArray; 
     nameParam.Value = nameList.ToArray(); 
     nameParam.Size = nameList.Count; 

     // You need this param for output 
     cmd.Parameters.Add("ret", OracleDbType.RefCursor).Direction = ParameterDirection.Output; 
     cmd.Parameters.Add(idParam); 
     cmd.Parameters.Add(nameParam); 

     conn.Open(); 

     //If you need to read results ... 
     using (OracleDataReader dr = cmd.ExecuteReader()) 
     { 
      while (dr.Read()) 
      { 
       ... 
      } 
     } 
     conn.Close(); 
    } 
} 

Ale to jest bardziej skomplikowane, ponieważ musisz zdefiniować nowe typy dla procedury przechowywanej, takie jak

TYPE integer_list IS TABLE OF Your_table.id_column%TYPE INDEX BY BINARY_INTEGER; 
// same for names 

utworzyć typ schematu poziomie jak

create or replace TYPE T_ID_TABLE is table of number; 

a następnie wykorzystać je w procedura składowana, jak

PROCEDURE Your_Procedure_name(
     v_ret IN OUT SYS_REFCURSOR, 
     i_idList integer_list, 
     i_nameList string_list) 
    IS 
    begin 
    -- Store passed object id list to array 
idList T_ID_TABLE := T_ID_TABLE(); 
    ... 
    begin 

    -- Store passed object id list to array 
    idList.Extend(i_idList.Count); 
    FOR i in i_idList.first..i_idList.last loop 
    idList(i) := i_idList(i); 
    END LOOP;  

    ... 
END Your_Procedure_name; 
+0

Dzięki za odpowiedź. Dam ci szansę. – user2316634

+0

po uruchomieniu TYPE integer_list IS TABELA Your_table.id_cloumn INDEX INDEX BY BINARY_INTEGER; Pokazuje niepoprawną instrukcję sql –

+0

Wypróbuj 'CREATE OR REPLACE TYPE inst_id_list IS TABLE OF INSTRUMENT.Inst_Id% INDEX INDEX BINARY_INTEGER;'. Musisz zastąpić sugerowane argumenty EvgenyL rzeczywistymi obiektami, które już istnieją w twojej db. (np. id_inst jest polem w tabeli INSTRUMENT). – dipdapdop