Uzyskaj wartość parametru wyjściowego w ADO.NET


96

Moja procedura składowana ma parametr wyjściowy:

@ID INT OUT

Jak mogę to odzyskać za pomocą 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();
}

Odpowiedzi:


119

Pozostałe przedstawiono odpowiedź, ale w zasadzie wystarczy, aby stworzyć SqlParameter, ustawić Directionna Outputi dodać go do SqlCommand„s Parameterskolekcji. Następnie wykonaj procedurę składowaną i uzyskaj wartość parametru.

Korzystanie z przykładowego kodu:

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

Zachowaj ostrożność podczas pobierania Parameters[].Value, ponieważ typ musi być rzutowany z objecttego, co deklarujesz jako. I SqlDbTypeużywany podczas tworzenia SqlParameterpotrzeb, aby dopasować typ w bazie danych. Jeśli zamierzasz po prostu wyprowadzić go na konsolę, być może po prostu używasz Parameters["@Param"].Value.ToString()(jawnie lub niejawnie przez wywołanie Console.Write()lub String.Format()).

EDYCJA: Ponad 3,5 roku i prawie 20 tys. Wyświetleń i nikt nie zadał sobie trudu, aby wspomnieć, że nawet się nie skompilował z powodu określonego w moim komentarzu „bądź ostrożny” w oryginalnym poście. Miły. Naprawiono to w oparciu o dobre komentarze @Walter Stabosz i @Stephen Kennedy oraz dopasowanie edycji kodu aktualizacji w pytaniu z @abatishchev.


8
Nie potrzebujesz, conn.Close()ponieważ jest w usingbloku
Marcus

1
Myślę, że użycie int.MaxValue jako właściwości Size jest nieprawidłowe. int.MaxValue jest stałą o wartości 2 147 483 647. msdn.microsoft.com/en-us/library/… . Błąd jest nieszkodliwy w tym przykładzie, ponieważ typem danych jest Int i „W przypadku typów danych o stałej długości wartość Size jest ignorowana”, ale wystarczyłoby zero.
Walter Stabosz

.Value jest typu object, więc przypisanie jej bezpośrednio do int bez rzutowania nie będzie działać.
Stephen Kennedy

1
W przypadku tych, które używają DataReader, należy zamknąć go lub odczytać do końca danych, zanim będzie można wyświetlić parametry wyjściowe.
Garry English

56

Każdy, kto chce zrobić coś podobnego za pomocą czytnika z procedurą składowaną, powinien pamiętać, że czytnik musi być zamknięty, aby pobrać wartość wyjściową.

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
Brakowało mi faktu, że czytnik trzeba zamknąć przed odczytaniem parametru wyjściowego. Dziękuję za zwrócenie uwagi!
Nicklas Møller Jepsen

28

Nie mój kod, ale myślę, że to dobry przykład

źródło: 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
Tak, to prawda. Wystarczy ustawić właściwość ParameterDirection parametru. Nie potrzebujesz linii cn.Close () - zajmuje się tym blok using {}.
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();
}

Czcionka 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

Możesz otrzymać swój wynik za pomocą poniższego kodu:

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

Utwórz SqlParamObject, który zapewni Ci kontrolę nad dostępem do metod parametrów

:

SqlParameter param = new SqlParameter ();

Ustaw nazwę dla swojego parametru (powinna być taka sama, jak zadeklarowałbyś zmienną do przechowywania wartości w bazie danych)

: param.ParameterName = "@yourParamterName";

Wyczyść uchwyt wartości, aby przechowywać dane wyjściowe

: param.Value = 0;

Ustaw wybrany kierunek (w twoim przypadku powinien to być wyjście)

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


1

Dla mnie wygląda to bardziej jednoznacznie:

int? id = outputIdParam.Value to DbNull? default (int?): outputIdParam.Value;

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.