Вызов хранимой процедуры с возвращаемым значением

82

Я пытаюсь вызвать хранимую процедуру из своего приложения Windows C #. Хранимая процедура выполняется на локальном экземпляре SQL Server 2008. Я могу вызвать хранимую процедуру, но не могу получить значение обратно из хранимой процедуры. Эта хранимая процедура должна возвращать следующее число в последовательности. Я провел исследование в Интернете, и все сайты, которые я видел, указали на то, что это решение работает.

Код хранимой процедуры:

ALTER procedure [dbo].[usp_GetNewSeqVal]
      @SeqName nvarchar(255)
as
begin
      declare @NewSeqVal int
      set NOCOUNT ON
      update AllSequences
      set @NewSeqVal = CurrVal = CurrVal+Incr
      where SeqName = @SeqName

      if @@rowcount = 0 begin
print 'Sequence does not exist'
            return
      end

      return @NewSeqVal
end

Код, вызывающий хранимую процедуру:

SqlConnection conn = new SqlConnection(getConnectionString());
conn.Open();

SqlCommand cmd = new SqlCommand(parameterStatement.getQuery(), conn);
cmd.CommandType = CommandType.StoredProcedure;

SqlParameter param = new SqlParameter();

param = cmd.Parameters.Add("@SeqName", SqlDbType.NVarChar);
param.Direction = ParameterDirection.Input;
param.Value = "SeqName";

SqlDataReader reader = cmd.ExecuteReader();

Я также пробовал использовать a DataSetдля получения возвращаемого значения с тем же результатом. Что мне не хватает для получения возвращаемого значения из моей хранимой процедуры? Если потребуется дополнительная информация, дайте мне знать.

Уэсли
источник

Ответы:

165

В команду нужно добавить параметр возврата:

using (SqlConnection conn = new SqlConnection(getConnectionString()))
using (SqlCommand cmd = conn.CreateCommand())
{
    cmd.CommandText = parameterStatement.getQuery();
    cmd.CommandType = CommandType.StoredProcedure;
    cmd.Parameters.AddWithValue("SeqName", "SeqNameValue");

    var returnParameter = cmd.Parameters.Add("@ReturnVal", SqlDbType.Int);
    returnParameter.Direction = ParameterDirection.ReturnValue;

    conn.Open();
    cmd.ExecuteNonQuery();
    var result = returnParameter.Value;
}
Алекс Аза
источник
3
Вам также нужно добавить @ReturnValв хранимую процедуру?
muttley91
4
Нет, вам не нужно добавлять sp (оператор return запускает заполнение параметра, отмеченного ReturnValue)
ufosnowcat
10
Неважно, как вы назовете возвращаемый параметр val, кстати.
Клэй
Большое спасибо, я искал способ правильно получить возвращаемое значение, это действительно сработало для меня. здорово!
Освальдо Сапата
4
Возвращаемое значение хранимой процедуры следует использовать только для указания успеха (ноль) или сбоя / предупреждения (ненулевое значение), но не для возврата данных. Для этого используйте OUTPUTпараметр или набор результатов.
Дэн Гузман
5

Я знаю, что это старый, но я наткнулся на него с Google.

Если у вас есть возвращаемое значение в вашей хранимой процедуре, скажите «Return 1» - без использования выходных параметров.

Вы можете сделать следующее - «@RETURN_VALUE» незаметно добавляется к каждому командному объекту. НЕ ТРЕБУЕТСЯ ЯВНО ДОБАВЛЯТЬ

    cmd.ExecuteNonQuery();
    rtn = (int)cmd.Parameters["@RETURN_VALUE"].Value;
Гэри
источник
2
Привет, Гэри. У вас есть цитата?
Michael
5
Я не верю, что экземпляр cmd будет иметь параметр с именем RETURN_VALUE в SqlParameterCollection, если он не добавлен явно. Поэтому, если вы планируете использовать подход Гэри, описанный выше, убедитесь, что вы добавили cmd.Parameters.Add (new SqlParameter ("@ RETURN_VALUE", SqlDbType.Int)); cmd.Parameters ["@ RETURN_VALUE"]. Направление = ParameterDirection.ReturnValue; Однако я верю, что вам НЕ нужно добавлять @RETURN_VALUE в определение хранимой процедуры. Возможно, именно это имел в виду Гэри.
jbooker
4

Версия EnterpriseLibrary на моей машине имела другие параметры. Это работало:

        SqlParameter retval = new SqlParameter("@ReturnValue", System.Data.SqlDbType.Int);
        retval.Direction = System.Data.ParameterDirection.ReturnValue;
        cmd.Parameters.Add(retval);
        db.ExecuteNonQuery(cmd);
        object o = cmd.Parameters["@ReturnValue"].Value;
RaSor
источник
3

ExecuteScalar(); будет работать, но выходной параметр будет лучшим решением.

Джастин Диринг
источник
7
ExecuteScalar () не работает, пока вы не «выберете» возвращаемое значение.
Soori
2

У меня была аналогичная проблема с вызовом SP, возвращающим ошибку, что ожидаемый параметр не был включен. Мой код был следующим.
Хранимая процедура:

@Result int ВЫХОД

И С #:

            SqlParameter result = cmd.Parameters.Add(new SqlParameter("@Result", DbType.Int32));
            result.Direction = ParameterDirection.ReturnValue;

При устранении неполадок я понял, что хранимая процедура ДЕЙСТВИТЕЛЬНО ищет направление «InputOutput», поэтому следующее изменение устранило проблему.

            r

Result.Direction = ParameterDirection.InputOutput;

Павел
источник
1
«Выходные параметры» - это не то же самое, что возвращаемые значения хранимой процедуры, кстати.
Дай
0

Или если вы используете EnterpriseLibrary, а не стандартный ADO.NET ...

Database db = DatabaseFactory.CreateDatabase();
using (DbCommand cmd = db.GetStoredProcCommand("usp_GetNewSeqVal"))
{
    db.AddInParameter(cmd, "SeqName", DbType.String, "SeqNameValue");
    db.AddParameter(cmd, "RetVal", DbType.Int32, ParameterDirection.ReturnValue, null, DataRowVersion.Default, null);

    db.ExecuteNonQuery(cmd);

    var result = (int)cmd.Parameters["RetVal"].Value;
}
Дунк
источник
0

Это очень короткий пример возврата одного значения из процедуры:

SQL:

CREATE PROCEDURE [dbo].[MakeDouble] @InpVal int AS BEGIN 
SELECT @InpVal * 2; RETURN 0; 
END

C # -код:

int inpVal = 11;
string retVal = "?";
using (var sqlCon = new SqlConnection(
    "Data Source = . ; Initial Catalog = SampleDb; Integrated Security = True;"))
{
    sqlCon.Open();
    retVal = new SqlCommand("Exec dbo.MakeDouble " + inpVal + ";", 
        sqlCon).ExecuteScalar().ToString();
    sqlCon.Close();
}
Debug.Print(inpVal + " * 2 = " + retVal); 
//> 11 * 2 = 22
Майкл Борг
источник
-8

Я вижу, что другой закрыт. Итак, вот пример моего кода. Я думаю, вам не хватает строкового комментария cmd. Например, если моя процедура хранения называется вызовом: DBO.Test. Мне нужно было бы написать cmd = "DBO.test". Затем введите тип команды, равный процедуре сохранения, и бла-бла-бла

Connection.open();
String cmd="DBO.test"; //the command
Sqlcommand mycommand;
Дождь
источник