用返回值调用存储过程


80

我正在尝试从C#Windows应用程序调用存储过程。该存储过程在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();

我也尝试过使用aDataSet检索具有相同结果的返回值。我缺少从存储过程中获取返回值的东西吗?如果需要更多信息,请告诉我。

Answers:


162

您需要在命令中添加return参数:

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 2014年

4
不,您不必添加到sp(return语句触发填充带有ReturnValue标记的参数)
ufosnowcat 2014年

10
命名return val参数btw无关紧要。
粘土人

非常感谢,我一直在寻找一种适当获得回报价值的方法,这对我确实很有效。太棒了!
Oswaldo Zapata

4
存储过程的返回值应仅用于指示成功(零)或失败/警告(非零),而不用于返回数据。OUTPUT为此使用参数或结果集。
丹·古兹曼

5

我知道这很老了,但是我偶然发现了Google。

如果存储过程中有返回值,请说“ Return 1”-不使用输出参数。

您可以执行以下操作-将“ @RETURN_VALUE”静默添加到每个命令对象中。无需明确添加

    cmd.ExecuteNonQuery();
    rtn = (int)cmd.Parameters["@RETURN_VALUE"].Value;

2
嗨,加里。你碰巧被引用了吗?
2014年

5
我不相信cmd实例将具有SqlParameterCollection中以RETURN_VALUE命名的参数,除非明确添加它。因此,如果您考虑采用Gary的上述方法,请确保已添加cmd.Parameters.Add(new SqlParameter(“ @ RETURN_VALUE”,SqlDbType.Int));。cmd.Parameters [“ @ RETURN_VALUE”]。Direction = ParameterDirection.ReturnValue; 但是,我相信您不必在存储过程定义中添加@RETURN_VALUE。也许这就是加里的意思。
jbooker '16

4

ExecuteScalar()可以使用,但是输出参数将是一个更好的解决方案。


5
除非您“选择”返回值,否则ExecuteScalar()不起作用。
Soori

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;


2

我在SP调用中遇到了类似的问题,返回的错误是未包含预期参数。我的代码如下。
存储过程:

@Result int输出

和C#:

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

在故障排除中,我意识到存储过程实际上是在寻找“ InputOutput”的方向,因此以下更改解决了该问题。

            r

Result.Direction = ParameterDirection.InputOutput;


“输出参数”与存储过程返回值btw不同。

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;

伟大的答案,鼓掌拍手鼓掌
Janatbek Sharsheyev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.