从ADO.NET中的存储过程获取返回值

我知道还有另一个问题,几乎相同的标题,但它没有回答我的问题。 我有一个存储过程,它在插入后返回唯一标识符(@@ identity)。 我在服务器资源管理器中尝试了它,它按预期工作(@RETURN_VALUE = [identifier])。 在我的代码中,我添加了一个名为“@RETURN_VALUE”的参数,其中ReturnValue方向优先于任何其他参数,但是当我使用ExecuteNonQuery()运行我的查询时该参数保持为空。 我不知道我做错了什么。 我的SPROC:

ALTER PROCEDURE dbo.SetAuction ( @auctionID int, @itemID int, @auctionType tinyint, @reservationPrice int, @maxPrice int, @auctionEnd datetime, @auctionStart datetime, @auctionTTL tinyint, @itemName nchar(50), @itemDescription nvarchar(MAX), @categoryID tinyint, @categoryName nchar(50) ) AS IF @auctionID  0 BEGIN BEGIN TRAN T1 UPDATE Auction SET AuctionType = @auctionType, ReservationPrice = @reservationPrice, MaxPrice = @maxPrice, AuctionEnd = @auctionEnd, AuctionStart = @auctionStart, AuctionTTL = @auctionTTL WHERE AuctionID = @auctionID; UPDATE Item SET ItemName = @itemName, ItemDescription = @itemDescription WHERE ItemID = (SELECT ItemID FROM Auction WHERE AuctionID = @auctionID); COMMIT TRAN T1 RETURN @auctionID END ELSE BEGIN BEGIN TRAN T1 INSERT INTO Item(ItemName, ItemDescription, CategoryID) VALUES(@itemName, @itemDescription, @categoryID); INSERT INTO Auction(ItemID, AuctionType, ReservationPrice, MaxPrice, AuctionEnd, AuctionStart, AuctionTTL) VALUES(@@IDENTITY,@auctionType,@reservationPrice,@maxPrice,@auctionEnd,@auctionStart,@auctionTTL); COMMIT TRAN T1 RETURN @@IDENTITY END 

我的代码是:

  cmd.CommandText = cmdText; SqlParameter retval = new SqlParameter("@RETURN_VALUE", System.Data.SqlDbType.Int); retval.Direction = System.Data.ParameterDirection.ReturnValue; cmd.Parameters.Add(retval); cmd.Parameters.AddRange(parameters); cmd.Connection = connection; connection.Open(); cmd.ExecuteNonQuery(); return (int)cmd.Parameters["@RETURN_VALUE"].Value; 

刚尝试我的盒子,这对我有用:

在SQL Server中:

 DROP PROCEDURE TestProc; GO CREATE PROCEDURE TestProc AS RETURN 123; GO 

在C#中

  string cnStr = "Server=.;Database=Sandbox;Integrated Security=sspi;"; using (SqlConnection cn = new SqlConnection(cnStr)) { cn.Open(); using (SqlCommand cmd = new SqlCommand("TestProc", cn)) { cmd.CommandType = CommandType.StoredProcedure; SqlParameter returnValue = new SqlParameter(); returnValue.Direction = ParameterDirection.ReturnValue; cmd.Parameters.Add(returnValue); cmd.ExecuteNonQuery(); Assert.AreEqual(123, (int)returnValue.Value); } } 

我解决了这个问题:你必须将SqlCommand.CommandType设置为CommandType.StoredProcedure才能获得返回值和/或输出参数。 我还没有找到任何相关的文档,但现在一切正常。

你在TSQL中获得了EXEC的价值吗? 我想知道重构TSQL是否有帮助(并使用SCOPE_IDENTITY()

所以改变:

 COMMIT TRAN T1 RETURN @@IDENTITY 

至:

 SET @auctionID = SCOPE_IDENTITY() COMMIT TRAN T1 RETURN @auctionID 

(我也会将另一个@@IDENTITY更改为SCOPE_IDENTITY()


作为次要优化,您还可以使用:

 return (int)retval.Value; 

但事情的这一方应该从我能看到的“现状”开始(因此我专注于TSQL)。

有些人也可以使用这种简单而简短的方法来计算SP的返回值

在SQL中:

 Create Table TestTable ( Int Id ) CREATE PROCEDURE Proc_TestProc @Id AS Begin Set NOCOUNT ON //Use this line if you don't want to return any message from SQL Delete from TestTable where Id = @Id return 1 Set NOCOUNT OFF //NOCOUNT OFF is Optional for NOCOUNT ON property End 

Sql Server始终仅返回Int类型值。

在C#

 using (SqlConnection conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["TestConnectionString"].ToString())) using (SqlCommand cmd = new SqlCommand("Proc_TestProc", conn)) { cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@Id", 1); var returnParameter = cmd.Parameters.Add("@ReturnVal", SqlDbType.Int); returnParameter.Direction = ParameterDirection.ReturnValue; conn.Open(); cmd.ExecuteNonQuery(); var result = returnParameter.Value; } 

您还可以使用以下命令检查SQL中的返回值:

 DECLARE @return_status int; EXEC @return_status = dbo.[Proc_TestProc] 1; SELECT 'Return Status' = @return_status; print 'Returned value from Procedure: ' + Convert(varchar, @return_status); // Either previous or this line both will show you the value of returned value 

您可以在普通查询中使用之前使用的标准方法,但在Sql命令中,您必须在存储过程名称之前编写EXEC,并且不要使用如下命令类型:

  SqlConnection con = new SqlConnection(["ConnectionString"]) SqlCommand com = new SqlCommand("EXEC _Proc @id",con); com.Parameters.AddWithValue("@id",["IDVALUE"]); con.Open(); SqlDataReader rdr = com.ExecuteReader(); ArrayList liste = new ArrayList(); While(rdr.Read()) { liste.Add(rdr[0]); //if it returns multiple you can add them another arrays=> liste1.Add(rdr[1]) .. } con.Close();