Obtenir la valeur du paramètre de sortie dans ADO.NET

96

Ma procédure stockée a un paramètre de sortie:

@ID INT OUT

Comment puis-je récupérer cela en utilisant ado.net?

using (SqlConnection conn = new SqlConnection(...))
{
    SqlCommand cmd = new SqlCommand("sproc", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    // add parameters

    conn.Open();

    // *** read output parameter here, how?
    conn.Close();
}
abatishchev
la source

Réponses:

119

Les autres spectacles de réponse, mais essentiellement il vous suffit de créer un SqlParameter, réglez le Directionà Output, et l' ajouter à la SqlCommandde Parameterscollection. Exécutez ensuite la procédure stockée et récupérez la valeur du paramètre.

En utilisant votre exemple de code:

// SqlConnection and SqlCommand are IDisposable, so stack a couple using()'s
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("sproc", conn))
{
   // Create parameter with Direction as Output (and correct name and type)
   SqlParameter outputIdParam = new SqlParameter("@ID", SqlDbType.Int)
   { 
      Direction = ParameterDirection.Output 
   };

   cmd.CommandType = CommandType.StoredProcedure;
   cmd.Parameters.Add(outputIdParam);

   conn.Open();
   cmd.ExecuteNonQuery();

   // Some various ways to grab the output depending on how you would like to
   // handle a null value returned from the query (shown in comment for each).

   // Note: You can use either the SqlParameter variable declared
   // above or access it through the Parameters collection by name:
   //   outputIdParam.Value == cmd.Parameters["@ID"].Value

   // Throws FormatException
   int idFromString = int.Parse(outputIdParam.Value.ToString());

   // Throws InvalidCastException
   int idFromCast = (int)outputIdParam.Value; 

   // idAsNullableInt remains null
   int? idAsNullableInt = outputIdParam.Value as int?; 

   // idOrDefaultValue is 0 (or any other value specified to the ?? operator)
   int idOrDefaultValue = outputIdParam.Value as int? ?? default(int); 

   conn.Close();
}

Soyez prudent lorsque vous récupérez le Parameters[].Value, car le type doit être converti à partir objectde ce que vous déclarez. Et le SqlDbTypeutilisé lorsque vous créez les SqlParameterbesoins pour correspondre au type dans la base de données. Si vous voulez simplement le sortir sur la console, vous utilisez peut-être simplement Parameters["@Param"].Value.ToString()(explicitement ou implicitement via un appel Console.Write()ou String.Format()).

EDIT: Plus de 3,5 ans et près de 20k vues et personne n'avait pris la peine de mentionner qu'il n'a même pas été compilé pour la raison spécifiée dans mon commentaire "soyez prudent" dans le message original. Agréable. Correction du problème sur la base de bons commentaires de @Walter Stabosz et @Stephen Kennedy et pour correspondre à la modification du code de mise à jour dans la question de @abatishchev.

BQ.
la source
8
Vous n'avez pas besoin conn.Close()car c'est à l'intérieur d'un usingbloc
Marcus
1
Je pense que votre utilisation de int.MaxValue comme propriété Size est incorrecte. int.MaxValue est une constante avec la valeur 2 147 483 647. msdn.microsoft.com/en-us/library/… . L'erreur est inoffensive dans cet exemple car le type de données est Int et "Pour les types de données de longueur fixe, la valeur de Size est ignorée.", Mais un zéro aurait suffi.
Walter Stabosz
.Value est de type object, donc l'affecter directement à un int sans conversion ne fonctionnera pas.
Stephen Kennedy
1
Pour ceux qui utilisent un DataReader, vous devez le fermer ou lire jusqu'à la fin des données avant de pouvoir afficher les paramètres de sortie.
Garry English
56

Pour tous ceux qui cherchent à faire quelque chose de similaire à l'aide d'un lecteur avec la procédure stockée, notez que le lecteur doit être fermé pour récupérer la valeur de sortie.

using (SqlConnection conn = new SqlConnection())
{
    SqlCommand cmd = new SqlCommand("sproc", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    // add parameters
    SqlParameter outputParam = cmd.Parameters.Add("@ID", SqlDbType.Int);
    outputParam.Direction = ParameterDirection.Output;

    conn.Open();

    using(IDataReader reader = cmd.ExecuteReader())
    {
        while(reader.Read())
        {
            //read in data
        }
    }
    // reader is closed/disposed after exiting the using statement
    int id = outputParam.Value;
}
Nate Kindrew
la source
4
J'ai manqué le fait que le lecteur doit être fermé avant de lire le paramètre de sortie. Merci d'avoir fait remarquer cela!
Nicklas Møller Jepsen
28

Pas mon code, mais un bon exemple je pense

source: http://www.eggheadcafe.com/PrintSearchContent.asp?LINKID=624

using System; 
using System.Data; 
using System.Data.SqlClient; 


class OutputParams 
{ 
    [STAThread] 
    static void Main(string[] args) 
    { 

    using( SqlConnection cn = new SqlConnection("server=(local);Database=Northwind;user id=sa;password=;")) 
    { 
        SqlCommand cmd = new SqlCommand("CustOrderOne", cn); 
        cmd.CommandType=CommandType.StoredProcedure ; 

        SqlParameter parm= new SqlParameter("@CustomerID",SqlDbType.NChar) ; 
        parm.Value="ALFKI"; 
        parm.Direction =ParameterDirection.Input ; 
        cmd.Parameters.Add(parm); 

        SqlParameter parm2= new SqlParameter("@ProductName",SqlDbType.VarChar); 
        parm2.Size=50; 
        parm2.Direction=ParameterDirection.Output; 
        cmd.Parameters.Add(parm2); 

        SqlParameter parm3=new SqlParameter("@Quantity",SqlDbType.Int); 
        parm3.Direction=ParameterDirection.Output; 
        cmd.Parameters.Add(parm3);

        cn.Open(); 
        cmd.ExecuteNonQuery(); 
        cn.Close(); 

        Console.WriteLine(cmd.Parameters["@ProductName"].Value); 
        Console.WriteLine(cmd.Parameters["@Quantity"].Value.ToString());
        Console.ReadLine(); 
    } 
} 
WACM161
la source
2
Oui, c'est correct. Définissez simplement la propriété ParameterDirection du paramètre. Vous n'avez pas besoin de la ligne cn.Close () - le bloc using {} s'en charge.
MusiGenesis
6
string ConnectionString = ConfigurationManager.ConnectionStrings["DBCS"].ConnectionString;
using (SqlConnection con = new SqlConnection(ConnectionString))
{
//Create the SqlCommand object
SqlCommand cmd = new SqlCommand(“spAddEmployee”, con);

//Specify that the SqlCommand is a stored procedure
cmd.CommandType = System.Data.CommandType.StoredProcedure;

//Add the input parameters to the command object
cmd.Parameters.AddWithValue(“@Name”, txtEmployeeName.Text);
cmd.Parameters.AddWithValue(“@Gender”, ddlGender.SelectedValue);
cmd.Parameters.AddWithValue(“@Salary”, txtSalary.Text);

//Add the output parameter to the command object
SqlParameter outPutParameter = new SqlParameter();
outPutParameter.ParameterName = @EmployeeId”;
outPutParameter.SqlDbType = System.Data.SqlDbType.Int;
outPutParameter.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(outPutParameter);

//Open the connection and execute the query
con.Open();
cmd.ExecuteNonQuery();

//Retrieve the value of the output parameter
string EmployeeId = outPutParameter.Value.ToString();
}

Police http://www.codeproject.com/Articles/748619/ADO-NET-How-to-call-a-stored-procedure-with-output

Vinícius Todesco
la source
6
public static class SqlParameterExtensions
{
    public static T GetValueOrDefault<T>(this SqlParameter sqlParameter)
    {
        if (sqlParameter.Value == DBNull.Value 
            || sqlParameter.Value == null)
        {
            if (typeof(T).IsValueType)
                return (T)Activator.CreateInstance(typeof(T));

            return (default(T));
        }

        return (T)sqlParameter.Value;
    }
}


// Usage
using (SqlConnection conn = new SqlConnection(connectionString))
using (SqlCommand cmd = new SqlCommand("storedProcedure", conn))
{
   SqlParameter outputIdParam = new SqlParameter("@ID", SqlDbType.Int)
   { 
      Direction = ParameterDirection.Output 
   };

   cmd.CommandType = CommandType.StoredProcedure;
   cmd.Parameters.Add(outputIdParam);

   conn.Open();
   cmd.ExecuteNonQuery();

   int result = outputIdParam.GetValueOrDefault<int>();
}
Greg R Taylor
la source
3

Vous pouvez obtenir votre résultat par le code ci-dessous:

using (SqlConnection conn = new SqlConnection(...))
{
    SqlCommand cmd = new SqlCommand("sproc", conn);
    cmd.CommandType = CommandType.StoredProcedure;

    // add other parameters parameters

    //Add the output parameter to the command object
    SqlParameter outPutParameter = new SqlParameter();
    outPutParameter.ParameterName = "@Id";
    outPutParameter.SqlDbType = System.Data.SqlDbType.Int;
    outPutParameter.Direction = System.Data.ParameterDirection.Output;
    cmd.Parameters.Add(outPutParameter);

    conn.Open();
    cmd.ExecuteNonQuery();

    //Retrieve the value of the output parameter
    string Id = outPutParameter.Value.ToString();

    // *** read output parameter here, how?
    conn.Close();
}

la source
2

Créez le SqlParamObject qui vous donnerait le contrôle pour accéder aux méthodes sur les paramètres

:

SqlParameter param = nouveau SqlParameter ();

FIXER le nom de votre paramètre (il devrait être le même que vous auriez déclaré une variable pour contenir la valeur dans votre base de données)

: param.ParameterName = "@yourParamterName";

Effacez le conteneur de valeur pour contenir vos données de sortie

: param.Value = 0;

Définissez la direction de votre choix (dans votre cas, cela devrait être une sortie)

: param.Direction = System.Data.ParameterDirection.Output;

Sandeep Pandey
la source
1

Cela me semble plus explicite:

int? id = outputIdParam.Value est DbNull? par défaut (int?): outputIdParam.Value;

Genn
la source