Généralement, lorsque nous utilisons des procédures stockées, et que nous avons besoin de récupérer certaines informations qu'elles nous renvoient, avec .NET, nous avons plusieurs possibilités.

Petit Rappel

La 1ère méthode, c'est en récupérant le paramètre de sortie de la procédure stockée (si elle en a ...)

Voici un exemple de procédure stockée:

create procedure dbo.TestProcedure (
    @outputParameter varchar(20) output
)

as
begin
    select @outputParameter = 'Hello World'
end


Et voici un exemple de code que nous pourrions utiliser pour récupérer le paramètre de type OutPutParameter.

//...
oComm.Connection = oConn;
oComm.CommandText = "TestProcedure";
oComm.CommandType = CommandType.StoredProcedure;

OleDbParameter p = new OleDbParameter("@OutputParameter", OleDbType.VarChar, 20);
p.Direction = ParameterDirection.Output;

oComm.Parameters.Add(p);
oComm.ExecuteNonQuery();

Console.WriteLine(p.Value.ToString());
//..


Ici, nous aurons d'affiché : Hello World


La 2ième méthode, presque similaire à la 1ière, c'est de récupérer son paramètre de retour (Attention ! Si vous utilisez plusieurs types de paramètres, le paramètre de retour doit être inséré en premier !!).

Ma procédure stockée modifiée :

create procedure dbo.TestProcedure (
    @outputParameter varchar(20) output
)

as
begin
  select @outputParameter = 'Hello World !'
    return 13
end


Un exemple de code que je pourrai utiliser pour récupérer les différents paramètres.

OleDbParameter p = new OleDbParameter("@OutputParameter", OleDbType.VarChar, 20);
p.Direction = ParameterDirection.Output;

OleDbParameter p1 = new OleDbParameter("@ReturnValue", OleDbType.Integer);
p1.Direction = ParameterDirection.ReturnValue;

oComm.Parameters.Add(p1); //On l'ajoute en premier dans la liste des paramètres
oComm.Parameters.Add(p);

int c = oComm.ExecuteNonQuery();

Console.WriteLine("Value Output {0}", p.Value.ToString());
Console.WriteLine("Value Return {0}", p1.Value.ToString());
Console.WriteLine(" c = {0}", c.ToString());


Nous aurons d'affiché :

Value Output Hello World !
Value Return 13
 c = -1


Ici, c renvoit -1, parce que je n'ai pas eu d'ordre DML d'executé dans ma procédure. Dans le cas contraire, j'aurai eu le nombre de ligne affectée par la dernière requête ...


Fin du Rappel


Aujourd'hui, j'ai eu à utiliser 2 méthodes différentes en fonction du contexte dans lequel j'étais. Je dispose de procédures stockées effectuant plusieurs traitements différents (des Update et des Deletes dans une même procédure ...).

Comment faire si je veux récupérer certains paramètres ou informations liées à l'éxécution de cette procédure ?

Pour résoudre cette question, j'ai utilisé 2 procédés.

La 1ère méthode, c'est me servir de la fonction print au sein de ma procédure stockée (J'utilise Sybase et le provider OleDb). La fonction print permettra de soulever des warnings que nous pourrons récupérer grâce à l'évènement InfoMessage associé à l'objet Connection.


Exemple

Ma Procedure :

create procedure TestProcedure
As
Begin
select * from matable
    print ' Warning!!! '
End



Le code que l'on pourrait utiliser pour récupérer le message renvoyé par print :

//..
OleDbConnection oConn = new OleDbConnection(m_connectionString)
oConn.Open();
oConn.InfoMessage += new OleDbInfoMessageEventHandler(oConn_InfoMessage);


static void oConn_InfoMessage(object sender, OleDbInfoMessageEventArgs e)
{
    Console.WriteLine("Info Message ...");
    foreach (OleDbError err in e.Errors)
    {
        Console.WriteLine(err.Source + " ### " + err.NativeError + " ### " + err.Message); }
    }
}

Toutes les fois ou un warning (avec la fonction print) ou autre message d'information sera renvoyé, nous pourrons l'afficher grâce à InfoMessage (et le delegate OleDbInfoMessageEventHandler).


La deuxième méthode que j'ai employée me permettait de faire une vérification des données que j'avais insérées à différents niveaux de traitement de ma procédure de stockée. Je trouve cette méthode un peu brutale dans la mesure ou les traitements ne sont pas dissociés (des updates, delete, et select dans la même procédure stockée). L'idéal est d'avoir une procédure stockée qui effectue le traitement, une autre qu permet de renvoyer les lignes parmi lesquels nous verrons les résultats attendus.


exemple:

Ma Procedure :

create procedure TestProcedure
As
Begin

    update data

    select someData to Check

    Other update

    select someOtherData To Check

    //etc...

End



J'ai créé une méthode simple pour afficher les données d'un datatable :

private static void DisplayDataSet(DataTable dt)
{
    foreach (DataRow row in dt.Rows)
    {
        foreach (DataColumn column in dt.Columns)
        {
            Console.Write(row[column].ToString() + " ");
        }
        Console.WriteLine();
    }
}



et je récupère l'ensemble des selects pour les afficher de cette façon :

DataSet ds = new DataSet();
OleDbDataAdapter adapter = new OleDbDataAdapter(oComm);
adapter.Fill(ds);

foreach (DataTable dt in ds.Tables)
{
    DisplayDataSet(dt);
}



Ce dernier cas était pratique pour moi parce que dans une même procédure je faisais plusieurs traitements, et j'affichais quelques lignes à certains niveaux de traitement. Ce n'est toutefois par quelque chose que je mettrais en production !

Voilà!

A + et Bonne journée !