Come chiamare una funzione Oracle con un cursore REF come parametro out-parametro da C#?
-
28-10-2019 - |
Domanda
Sto utilizzando un prodotto che fornisce un'API di database basata sulle funzioni Oracle e sono in grado di chiamare le funzioni tramite ODP.NET in generale. Tuttavia, non riesco a capire come chiamare una funzione che include un cursore di riferimento come parametro out-parametro. Tutti i campioni che ho trovato finora chiamano una procedura con il parametro out-parametro o una funzione con il cursore REF come valore di ritorno. Ho provato a definire in modo simile i parametri, ma continua a ottenere l'errore che viene fornito il numero e il tipo di parametri errato.
Ecco l'intestazione della funzione (ovviamente offuscata):
FUNCTION GetXYZ(
uniqueId IN somepackage.Number_Type,
resultItems OUT somepackage.Ref_Type)
RETURN somepackage.Error_Type;
Queste sono le definizioni di tipo in "qualche package":
SUBTYPE Number_Type IS NUMBER(13);
TYPE Ref_Type IS REF CURSOR;
SUBTYPE Error_Type IS NUMBER;
E questo è il codice che ho provato:
string sql = "otherpackage.GetXYZ";
var getXYZCmd = OracleCommand oracleConnection.CreateCommand(sql);
getXYZCmd.CommandType = CommandType.StoredProcedure;
getXYZCmd.Parameters.Add("uniqueId", OracleDbType.Int32).Value = uniqueExplosionId;
getXYZCmd.Parameters.Add("resultItems", OracleDbType.RefCursor).Direction = ParameterDirection.Output;
getXYZCmd.Parameters.Add("return_value", OracleDbType.Int32).Direction = ParameterDirection.ReturnValue;
Ho provato i seguenti modi diversi per chiamare la funzione (ovviamente solo una alla volta):
var result = getXYZCmd.ExecuteNonQuery();
var reader = getXYZCmd.ExecuteReader();
var scalarResult = getXYZCmd.ExecuteScalar();
Ma ognuno di essi fallisce con il messaggio di errore:
Oracle.DataAccess.Client.OracleException: ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 15:
PLS-00306: wrong number or types of arguments in call to 'GETXYZ'
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored.
Quindi è generalmente possibile chiamare una funzione con un cursore REF come parametro out-parametro da C# con ODP.NET? Posso chiamare una funzione con la stessa struttura con un parametro Varchar2-Out invece del cursore REF senza problemi ...
A proposito, sto usando ODP.NET versione 2.112.2.0 da C#.NET 3.5 in Visual Studio 2008.
Grazie in anticipo per il vostro aiuto!
Soluzione
Sicuramente puoi. Ci sono alcuni gotcha di cui diffidare, ma ecco un caso di prova
create or replace function testodpRefCursor(
uniqueId IN NUMBER
,resultItems OUT NOCOPY SYS_REFCURSOR) RETURN NUMBER
IS
BEGIN
OPEN resultItems for select level from dual connect by level < uniqueId ;
return 1;
END testodpRefCursor;
- Ho scoperto che le funzioni piace avere il returnValue come IL PRIMO parametro nella raccolta
- BindByName è per impostazione predefinita false, quindi è default legarsi per posizione
Altrimenti è abbastanza semplice:
OracleCommand cmd = new OracleCommand("TESTODPREFCURSOR", con);
cmd.CommandType = CommandType.StoredProcedure;
cmd.BindByName = true;
// Bind
OracleParameter oparam = cmd.Parameters.Add("ReturnValue", OracleDbType.Int64);
oparam.Direction = ParameterDirection.ReturnValue ;
OracleParameter oparam0 = cmd.Parameters.Add("uniqueId", OracleDbType.Int64);
oparam0.Value = 5 ;
oparam0.Direction = ParameterDirection.Input;
OracleParameter oparam1 = cmd.Parameters.Add("resultItems", OracleDbType.RefCursor);
oparam1.Direction = ParameterDirection.Output;
// Execute command
OracleDataReader reader;
try
{
reader = cmd.ExecuteReader();
while(reader.Read() ){
Console.WriteLine("level: {0}", reader.GetDecimal(0));
}
} ...
Ora per altri campioni vai alla tua oracle home directory e guarda @ i campioni di cursore ref in odp.net
Ad esempio: %Oracle Client Home % odp.net samples 4 refcursor
hth