Отримати значення вихідного параметра в ADO.NET


96

Моя збережена процедура має вихідний параметр:

@ID INT OUT

Як я можу отримати це за допомогою 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();
}

Відповіді:


119

Інший відповідь показує , що це, але по суті вам просто потрібно створити SqlParameter, встановити , Directionщоб Output, і додати його в SqlCommand«s Parametersколекції. Потім виконайте збережену процедуру та отримайте значення параметра.

Використовуючи зразок коду:

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

Будьте обережні при отриманні Parameters[].Value, оскільки тип повинен бути відтворений з objectтого, що ви заявляєте. І SqlDbTypeвикористовується при створенні SqlParameterпотреб для відповідності типу в базі даних. Якщо ви збираєтеся просто вивести його на консоль, можливо, ви просто використовуєте Parameters["@Param"].Value.ToString()(або явно, або неявно через Console.Write()або String.Format()виклик).

РЕДАГУВАТИ: Більше 3,5 років та майже 20 тис. Переглядів, і ніхто не потрудився згадати, що він навіть не склався з причини, зазначеної в моєму коментарі "будь обережним" в оригінальному дописі. Приємно. Виправлено на основі хороших коментарів від @Walter Stabosz та @Stephen Kennedy та відповідно до редагування коду оновлення у питанні від @abatishchev.


8
Вам не потрібно, conn.Close()як це всередині usingблоку
Маркус

1
Я вважаю, що ваше використання int.MaxValue як властивості Size є неправильним. int.MaxValue - це константа зі значенням 2 147 483 647. msdn.microsoft.com/en-us/library/… . У цьому прикладі помилка нешкідлива, оскільки тип даних - Int і "Для типів даних із фіксованою довжиною значення Size ігнорується.", Але достатньо було б нуля.
Вальтер Стабош

.Value є об'єктом типу, тому присвоєння його безпосередньо int-у без кастингу не буде працювати.
Стівен Кеннеді,

1
Для тих, хто використовує DataReader, ви повинні закрити його або прочитати до кінця даних, перш ніж зможете переглянути вихідні параметри.
Garry English

56

Для тих, хто хоче зробити щось подібне, використовуючи зчитувач із збереженою процедурою, зауважте, що зчитувач повинен бути закритий для отримання вихідного значення.

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
Я пропустив той факт, що зчитувач повинен бути закритий перед зчитуванням вихідного параметра. Дякуємо, що вказали на це!
Nicklas Møller Jepsen

28

Не мій код, але хороший приклад, я думаю

джерело: 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
Так, це правильно. Просто встановіть властивість ParameterDirection параметра. Вам не потрібен рядок cn.Close () - блок {} подбає про це.
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();
}

Шрифт 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

Ви можете отримати свій результат за кодом нижче:

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

Створіть SqlParamObject, який дасть вам можливість контролювати методи доступу до параметрів

:

SqlParameter param = новий SqlParameter ();

ВСТАНОВИТИ Ім'я для вашого параметра (воно повинно бути таким самим, як ви б оголосили змінну для зберігання значення у вашій базі даних)

: param.ParameterName = "@yourParamterName";

Зніміть власник значення, щоб утримувати вихідні дані

: param.Value = 0;

Встановіть напрямок за вашим вибором (у вашому випадку це має бути вихід)

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


1

Для мене це виглядає більш чітко:

int? id = outputIdParam.Value - DbNull? за замовчуванням (int?): outputIdParam.Value;

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.