Exécuter un oracle de la Fonction qui retourne une référence curseur en C#
J'ai un package oracle avec une procédure qui a une sortie de référence curseur. Ma compréhension est que c'est assez standard.
Ce que je n'aime pas, c'est le fait que j'ai dû écrire des tonnes de code pour voir la sortie. J'ai donc demandé à cette question et il s'avère que je peux obtenir ce que je veux par la création d'une fonction qui encapsule la procédure.
Mise à jour: Semble que je n'ai pas besoin de la fonction de plus, mais il peut être utile de savoir de toute façon pour ceux qui sont curieux de voir l'original de la question et de la réponse des mises à jour.
Voici la fonction
FUNCTION GetQuestionsForPrint (user in varchar2)
RETURN MYPACKAGE.refcur_question
AS
OUTPUT MYPACKAGE.refcur_question;
BEGIN
MYPACKAGE.GETQUESTIONS(p_OUTPUT => OUTPUT,
p_USER=> USER ) ;
RETURN OUTPUT;
END;
et voici ce que je fais pour l'exécuter en SQL Developer
var r refcursor;
exec :r := mypackage.getquestionsForPrint('OMG Ponies');
print r;
Donc à partir de maintenant je vais probablement ajouter la ForPrint fonctions à tous mes procédures.
Cela m'a fait penser, peut-être que les fonctions sont ce que je veux et je n'ai pas besoin de procédures.
Pour tester ce que j'ai essayé de l'exécution de la fonction .NET, sauf que je ne peut pas le faire. Est-ce vraiment la façon dont il est.
using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
cnn.Open();
OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.Parameters.Add ( "p_USER", "OMG Ponies");
cmd.Connection = cnn;
OracleDataReader rdr = cmd.ExecuteReader();
while (rdr.Read())
{
Console.WriteLine(rdr.GetOracleValue(0));
}
Console.ReadLine();
}
Donc, je reçois le message d'erreur.
getquestionsForPrint is not a procedure or is undefined
J'ai essayé ExecuteScalar ainsi avec le même résultat.
MODIFIER Prendre Slider345 conseils, j'ai également essayé le réglage de la commande le type de texte et à l'aide de l'instruction suivante et je reçois
non valide instruction SQL
mypackage.getquestionsForPrint('OMG Poinies');
et
var r refcursor; exec :r := mypackage.getquestionsForPrint('OMG Poinies');
À l'aide de Abhi de variation pour le texte de la commande
select mypackage.getquestionsForPrint('OMG Poinies') from dual
entraîné
L'instruction à "0x61c4aca5"
référencé la mémoire à "0x00000ce1". L'
la mémoire ne peut pas être "read".
Suis-je tout simplement aboiements le mauvais arbre?
Mise à jour
En essayant d'ajouter un paramètre de sortie n'aide pas.
cmd.Parameters.Add(null, OracleDbType.RefCursor, ParameterDirection.Output);
Pas sûr de ce que l' nom doit être depuis sa la valeur de retour d'une fonction (j'ai essayé null, chaîne vide, mypackage.getquestionsForPrint), mais dans tous les cas, il vient de résultats dans
ORA-06550: ligne 1, colonne 7:
PLS-00306: mauvais nombre ou les types de
les arguments en appel à
'getquestionsForPrint'
Montage Final (je l'espère)
Apparemment Guddie demandé un question similaire 3 mois après je l'ai fait. Il a obtenu la réponse qui est à
- Régler votre commande de texte à un bloc anonyme
- Lier un paramètre à l'ref curseur de réglage de la direction de la sortie
- Appel Exécuter non lecteur.
- Puis utilisez votre paramètre
using (OracleConnection cnn = new OracleConnection("Data Source=Test;User Id=Test;Password=Test;"))
{
cnn.Open();
OracleCommand cmd = new OracleCommand("mypackage.getquestionsForPrint");
cmd.CommandType = CommandType.Text;
cmd.CommandText = "begin " +
" :refcursor1 := mypackage.getquestionsForPrint('OMG Ponies') ;" +
"end;";
cmd.Connection = cnn;
OracleDataAdapter da = new OracleDataAdapter(cmd);
cmd.ExecuteNonQuery();
Oracle.DataAccess.Types.OracleRefCursor t = (Oracle.DataAccess.Types.OracleRefCursor)cmd.Parameters[0].Value;
OracleDataReader rdr = t.GetDataReader();
while(rdr.Read())
Console.WriteLine(rdr.GetOracleValue(0));
Console.ReadLine();
}
désolé manqué sur la copie d'une façon
Conrad, vous n'avez pas besoin de le wrapper - j'ai mis à jour la question précédente. Ne sais pas C# ne peut donc pas commenter sur cette partie. Personnellement - et je suis sûr que beaucoup de gens de me tirer vers le bas sur ce, je dirais, en général, une procédure devrait faire de la quantité de travail et peuvent avoir un impact à la fois sur des données qui est et n'est pas passé (que vous n'avez pas nécessairement connaître), et une fonction doit retourner un résultat basé sur le passé de données, et de préférence pas d'effets secondaires. Mais c'est ce qui est le plus approprié pour ce que vous faites. Aller en arrière et de changer de vieilles code est rare d'en mettre beaucoup, j'aurais pensé.
J'ai fait face à des difficultés similaires. Donc j'ai dû changer mes fonctions à des procédures stockées. Je n'ai pas de réponse étant donné que cette question est ancienne. La modification de la CommandType suggestion donnée par Slider345 ne fonctionne pas si votre fonction est de retour une REFCURSOR. Il ne fonctionnera que si vous avez une fonction scalaire, qui retourne une valeur et non pas un jeu d'enregistrements. Dans ce cas, vous devez utiliser votre fonction dans une requête "SELECT function_name DE DOUBLE". Peut-être vous pouvez essayer cette approche sur la fonction ci-dessus. Changer votre commandtype de TEXTE, puis modifiez la syntaxe pour appeler la fonction.
Avez-vous vu le "Test du CURSEUR REF Procédure à partir de C#" de la section ce lien -- au milieu de la page pour moi.
OriginalL'auteur Conrad Frix | 2010-08-20
Vous devez vous connecter pour publier un commentaire.
Je n'ai pas testé avec une fonction, mais pour mes procédures stockées. - Je spécifier le paramètre de sortie pour le refCursor.
Si vous êtes en mesure d'obtenir la fonction de travail avec le CommandType.Texte. Je me demande si vous pouvez essayer d'ajouter le paramètre ci-dessus, sauf avec la direction:
Je suis de l'utilisation d'Oracle.DataAccess version 2.111.6.0
Frix je crois que vous pouvez attribuer n'importe quel nom que vous voulez, en spécifiant la direction du paramètre comme valeur de retour, il serait de la carte des résultats, je n'ai pas testé encore. Je suis aussi tombée sur ce lien retour ref_cursor à partir de la fonction. Ils utilisent la méthode ExecuteNonQuery et l'accès le curseur via le paramètre. Est-ce la façon alternative vous trouvé?
qu'il a fait. Profitez de votre reprise de l'insigne
L'alternative que j'ai trouvé est d'utiliser les procs directement et oublier l'écriture de fonctions wrapper. Voir le bas de la question
Frix Yay j'ai deux badges maintenant =). Merci!!!!
OriginalL'auteur Peter C
J'ai dû aller en haut et en bas entre la question et les réponses à comprendre le code complet qui fonctionne. Donc, je donne le code complet ici qui a fonctionné pour moi pour les autres -
Espère que cela aide.
OriginalL'auteur th1rdey3
Ma conjecture est que vous ne pouvez pas appeler une fonction à un objet de Commande de type 'Stockée'. Pouvez-vous essayer un objet de Commande de type 'Texte' et 'exec' la fonction dans le Texte de la Commande?
OriginalL'auteur Slider345
Je sais que c'est un assez vieux post, mais depuis qu'il m'a fallu si longtemps pour comprendre toutes les règles impliqués dans l'obtention d' .NET de lutter contre les "nice" avec Oracle, j'ai pensé mettre ce conseil là pour quelqu'un d'autre dans cette situation délicate.
J'ai souvent appel de procédures stockées Oracle qui de retour d'un REF_CURSOR dans notre environnement.NET 3.5 contre Oracle 11g). Pour une fonction, vous pouvez en effet le nom du paramètre tout ce que vous voulez, mais vous devez configurer son
System.Data.ParameterDirection
=ParameterDirection.ReturnValue
puisExecuteNonQuery
contre laOracleCommand
objet. À ce moment, la valeur de ce paramètre sera le ref_cursor que l'Oracle de la fonction retournée. Juste lancer la valeur comme uneOracleDataReader
et boucle à travers leOracleDataReader
.J'ai poster le code complet, mais j'ai écrit la couche d'accès aux données dans VB.NET il y a des années, et la majeure partie du code de la consommation de la couche d'accès aux données (notre intranet de l'entreprise) est en C#. J'ai pensé que le mélange des langues dans une seule réponse serait le plus grand faux pas.
OriginalL'auteur