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();
}
Aucune une telle chose comme un "racleCommand", post code réel.
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