Ottieni il valore del parametro di output in ADO.NET


96

La mia stored procedure ha un parametro di output:

@ID INT OUT

Come posso recuperarlo utilizzando 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();
}

Risposte:


119

Gli altri spettacoli di risposta, ma in sostanza, non vi resta che creare un SqlParameter, impostare la Directiona Output, e aggiungere al SqlCommand's Parametersdi raccolta. Quindi eseguire la procedura memorizzata e ottenere il valore del parametro.

Utilizzando il codice di esempio:

// 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();
}

Fai attenzione quando ottieni il Parameters[].Value, poiché il tipo deve essere lanciato da objectquello che lo stai dichiarando. E l' SqlDbTypeusato quando si creano le SqlParameteresigenze per abbinare il tipo nel database. Se hai intenzione di inviarlo solo alla console, potresti semplicemente usare Parameters["@Param"].Value.ToString()(esplicitamente o implicitamente tramite una chiamata Console.Write()o String.Format()).

EDIT: Oltre 3,5 anni e quasi 20k visualizzazioni e nessuno si era preso la briga di dire che non si era nemmeno compilato per il motivo specificato nel mio commento "attenzione" nel post originale. Bello. Risolto il problema in base ai buoni commenti di @Walter Stabosz e @Stephen Kennedy e per abbinare la modifica del codice di aggiornamento nella domanda di @abatishchev.


8
Non è necessario conn.Close()che sia all'interno di un usingblocco
Marcus

1
Penso che il tuo utilizzo di int.MaxValue come proprietà Size non sia corretto. int.MaxValue è una costante con il valore 2.147.483.647. msdn.microsoft.com/en-us/library/… . L'errore è innocuo in questo esempio perché il tipo di dati è Int e "Per i tipi di dati a lunghezza fissa, il valore di Dimensione viene ignorato.", Ma uno zero sarebbe stato sufficiente.
Walter Stabosz

.Value è di tipo object, quindi assegnarlo direttamente a un int senza casting non funzionerà.
Stephen Kennedy,

1
Per coloro che utilizzano un DataReader, è necessario chiuderlo o leggere fino alla fine dei dati prima di poter visualizzare i parametri di output.
Garry English

56

Per chiunque cerchi di fare qualcosa di simile usando un lettore con la stored procedure, si noti che il lettore deve essere chiuso per recuperare il valore di output.

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;
}

4
Mi è sfuggito il fatto che il lettore deve essere chiuso prima di leggere il parametro di output. Grazie per la segnalazione!
Nicklas Møller Jepsen

28

Non il mio codice, ma un buon esempio credo

fonte: 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(); 
    } 
} 

2
Sì, è corretto. Basta impostare la proprietà ParameterDirection del parametro. Non hai bisogno della riga cn.Close () - il blocco using {} si occupa di questo.
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();
}

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


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>();
}

3

Puoi ottenere il tuo risultato dal codice sottostante:

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();
}

2

Crea l'oggetto SqlParamObject che ti darà il controllo per accedere ai metodi sui parametri

:

SqlParameter param = new SqlParameter ();

IMPOSTA il nome per il tuo parametro (dovrebbe essere uguale a come avresti dichiarato una variabile per contenere il valore nel tuo DataBase)

: param.ParameterName = "@yourParamterName";

Cancella il contenitore del valore per conservare i dati di output

: param.Value = 0;

Imposta la direzione che preferisci (nel tuo caso dovrebbe essere Output)

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


1

Sembra più esplicito per me:

int? id = outputIdParam.Value è DbNull? predefinito (int?): outputIdParam.Value;

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.