Tornando più cursori ref da procedure Oracle utilizzando DAAB & C #
-
16-09-2019 - |
Domanda
Voglio restituire i dati da una routine Oracle per popolare alcuni controlli Label. La procedura accetta 26 parametri di input (variabili di ricerca) e restituisce 3 cursori uscita. Ho avuto successo la restituzione dei dati da una procedura che restituisce un unico cursore ref usando OracleCommand, un DataAdapter, e un DataSet, ma sono stato avere tutti i tipi di problemi che restituiscono dati da una procedura di ritorno multipli cursori rif.
Stavo cercando di utilizzare DAAB dalla Enterprise Library, ma non ha avuto successo (post originale). Io ora sono tornato ad un OracleCommand in base al largo i messaggi di Oracle e altri siti dev. Sto ancora tornando zero righe. Posso restituire i nomi delle colonne dai miei lettori che utilizzano "rdr_p_cursor_detail.GetName (0);", ma quando cerco di restituire un valore ottengo "Operazione non è valida a causa dello stato corrente dell'oggetto" errore.
//Open the connection to Oracle.
OracleConnection cn = new OracleConnection(ConfigurationHelper.ConnectionStringSlabProcedures);
OracleCommand cmd = new OracleCommand();
cn.Open();
cmd.Connection = cn;
try
{
//Set the command text (SQL) of the Oracle command to the stored procedure "getSlab", which returns slab details.
cmd.CommandText = ConfigurationHelper.ProcuedurePackageSchema + "." +
ConfigurationHelper.ProcuedurePackageName + "." +
"getSlab";
//...and specify the command as a stored procedure.
cmd.CommandType = CommandType.StoredProcedure;
//Add the input and output parameters.
cmd.Parameters.Add("rb_category", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("rb_category_value", OracleDbType.Varchar2).Value = slabID;
cmd.Parameters.Add("rb_type ", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("rb_chem_value", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_inside_only", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_appl_pending", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_appl_soft_approved", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_appl_hard_approved", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_appl_mechanically", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_as_cast", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_as_dispoed", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_chem_match", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_near_match", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("txt_width_min", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_width_max", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_quality_min", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_quality_max", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_days_old_min", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_days_old_max", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_days_rev_min", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_days_rev_max", OracleDbType.Int32).Value = 0;
cmd.Parameters.Add("txt_reviewer", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_excl_hr", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_excl_cr", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_excl_galv", OracleDbType.Varchar2).Value = string.Empty;
cmd.Parameters.Add("cb_excl_tin", OracleDbType.Varchar2).Value = string.Empty;
//Add the ref-cursors as output parameters
OracleParameter p_cursor_detail = cmd.Parameters.Add("p_cursor_detail", OracleDbType.RefCursor);
p_cursor_detail.Direction = ParameterDirection.Output;
OracleParameter p_cursor_comments = cmd.Parameters.Add("p_cursor_comments", OracleDbType.RefCursor);
p_cursor_comments.Direction = ParameterDirection.Output;
OracleParameter p_cursor_grades = cmd.Parameters.Add("p_cursor_grades", OracleDbType.RefCursor);
p_cursor_grades.Direction = ParameterDirection.Output;
// Execute the command
cmd.ExecuteNonQuery();
// Construct an OracleDataReader from the REF CURSOR
OracleDataReader rdr_p_cursor_detail = ((OracleRefCursor)p_cursor_detail.Value).GetDataReader();
if (rdr_p_cursor_detail.Read())
{
//This would return an error if it was outside this if statement.
//"Operation is not valid due to the current state of the object."
OracleString oracleString1 = rdr_p_cursor_detail.GetOracleString(1);
LabelSlabID.Text = oracleString1.ToString();
//This correctly returns column name/header.
//LabelSlabID.Text = rdr_p_cursor_detail.GetName(0);
}
else
{
LabelSlabID.Text = "No Data";
}
rdr_p_cursor_detail.Close();
rdr_p_cursor_detail.Dispose();
p_cursor_detail.Dispose();
p_cursor_comments.Dispose();
p_cursor_grades.Dispose();
}
catch (Exception e)
La procedura oracle troncato:
PROCEDURE getSlab
(rb_category IN VARCHAR2
,rb_category_value IN VARCHAR2
,rb_type IN VARCHAR2
,rb_chem_value IN VARCHAR2
,cb_inside_only IN VARCHAR2
,cb_appl_pending IN VARCHAR2
,cb_appl_soft_approved IN VARCHAR2
,cb_appl_hard_approved IN VARCHAR2
,cb_appl_mechanically IN VARCHAR2
,cb_as_cast IN VARCHAR2
,cb_as_dispoed IN VARCHAR2
,cb_chem_match IN VARCHAR2
,cb_near_match IN VARCHAR2
,txt_width_min IN NUMBER
,txt_width_max IN NUMBER
,txt_quality_min IN NUMBER
,txt_quality_max IN NUMBER
,txt_days_old_min IN NUMBER
,txt_days_old_max IN NUMBER
,txt_days_rev_min IN NUMBER
,txt_days_rev_max IN NUMBER
,txt_reviewer IN VARCHAR2
,cb_excl_hr IN VARCHAR2
,cb_excl_cr IN VARCHAR2
,cb_excl_galv IN VARCHAR2
,cb_excl_tin IN VARCHAR2
,cur_OUT OUT t_cursor1
,cur_OUT1 OUT t_cursor2
,cur_OUT2 OUT t_cursor3) IS
--All the queries and so forth are performed and data sent to temp tables.
OPEN v_cursor1 FOR
SELECT * FROM TABLE(CAST(g_slab_table AS getSlab_table));
cur_OUT := v_cursor1;
OPEN v_cursor2 FOR
SELECT * FROM TABLE(CAST(g_comment_table AS getComment_table));
cur_OUT1 := v_cursor2;
OPEN v_cursor3 FOR
SELECT * FROM TABLE(CAST(g_grades_table AS getGrades_table));
cur_OUT2 := v_cursor2;
Tutte le idee? Sono appoggiato verso l'uso improprio del lettore, ma non riesco a capire cosa mi manca. Grazie.
Soluzione
Sembra essere Oracle stored procedure. Ho modificato l'uscita del cursore, hard-codifica una selezione da "duale", e i dati e le intestazioni delle colonne stanno tornando buone.
...
Lezione 1) Se si riceve un errore "Operazione non è valida a causa dello stato corrente dell'oggetto", la connessione è chiusa o non ci sono file di dati che vengono restituiti.
Lezione 2) Non fidarti dei tuoi scrittori di procedura (se non si sta scrivendo il codice db da soli). Prendete i 30 minuti per rivedere il loro codice, se pensate che il vostro codice dovrebbe funzionare. Si può risparmiare una dozzina di ore sprecate così:.)
Grazie a tutti.
Altri suggerimenti
Ho passato quasi lo stesso scenario ... Il problema principale era che non c'erano righe di dati da restituire. Che può essere controllato utilizzando:
if(reader.HasRows)
L'altra cosa che ha risolto il mio problema era l'uso di
reader.NextResult()
per arrivare al prossimo cursore restituita (out).