Retour plusieurs curseurs REF de la procédure Oracle à l'aide de DAAB & C #
-
16-09-2019 - |
Question
Je souhaite retourner les données d'une procédure Oracle pour remplir certains contrôles d'étiquette. La procédure accepte 26 paramètres d'entrée (variable de recherche) et renvoie 3 curseurs de sortie. J'ai réussi à renvoyer des données d'une procédure qui renvoie un seul curseur REF à l'aide d'OracleCommand, d'un DataAdapter et d'un ensemble de données, mais j'ai eu toutes sortes de problèmes de retour des données d'une procédure renvoyant plusieurs curseurs REF.
J'essayais d'utiliser DAAB à partir de la bibliothèque Enterprise, mais je n'avais pas de succès (post original). Je suis maintenant retourné sur un OracleCommand basé sur les articles d'Oracle et d'autres sites de développement. Je retourne toujours zéro lignes. Je peux retourner les noms de colonne de mes lecteurs à l'aide de "RDR_P_CURSOR_DETAIL.getName (0);", mais lorsque j'essaie de renvoyer une valeur, je reçois une "opération n'est pas valide en raison de l'état actuel de l'objet." Erreur.
//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 procédure Oracle tronquée:
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;
Des idées? Je me penche vers une mauvaise utilisation des lecteurs, mais je ne peux pas comprendre ce qui me manque. Merci.
La solution
Il semble que ce soit la procédure stockée par Oracle. J'ai modifié la sortie du curseur, codant dur une sélection à partir de "double", et les en-têtes de données et de colonnes reviennent bien.
Alors...
Leçon 1) Si vous recevez une erreur "l'opération n'est pas valide en raison de l'état actuel de l'objet", votre connexion est fermée ou aucune ligne de données est renvoyée.
Leçon 2) Ne faites pas confiance à vos rédacteurs de procédures (si vous n'écrivez pas le code DB vous-même). Prenez les 30 minutes pour revoir leur code si vous pensez que votre code devrait fonctionner. Cela peut vous faire économiser une douzaine d'heures perdues :).
Merci a tous.
Autres conseils
J'ai traversé presque le même scénario ... Le principal problème était qu'il n'y avait pas de lignes de données retournées. Qui peut être vérifié en utilisant:
if(reader.HasRows)
L'autre chose qui a résolu mon problème était l'utilisation de
reader.NextResult()
pour accéder au curseur (extérieur) prochain suivant.