【问题标题】:Getting return value from stored procedure in ADO.NET从 ADO.NET 中的存储过程获取返回值
【发布时间】:2010-07-22 13:15:13
【问题描述】:

我有一个存储过程,它在插入@@identity 后返回唯一标识符。我在服务器资源管理器中尝试过,它按预期工作@RETURN_VALUE = [identifier]

在我的代码中,我添加了一个名为 @RETURN_VALUE 的参数,它首先使用 ReturnValue 方向,而不是任何其他参数,但是当我使用 ExecuteNonQuery() 运行查询时,该参数仍然为空。我不知道我做错了什么。

存储过程

 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

C# 代码

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;

【问题讨论】:

  • 当你说“空”时 - 你得到一个异常说 Value 为空? (如果它为空,则转换将失败)。还是0?
  • 顺便说一句,@@IDENTITY 很危险;你应该改用SCOPE_IDENTITY()
  • 在这种情况下,返回值 0:尝试 SCOPE_IDENTITY(),或者至少是一个测试值

标签: c# ado.net


【解决方案1】:

刚刚在我的盒子上试了一下,这对我有用:

在 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);
            }
        }

【讨论】:

  • 我扩展了这个例子。也许你会试试这个。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    你在 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)。

    【讨论】:

    • 更改了您的建议,但没有效果。我使用“EXEC SetAuction @auctionID, ...”作为命令文本。如果我从服务器资源管理器 (Visual Studio) 运行它,我会得到返回值。
    【解决方案4】:

    有些人也可以使用这种简单而简短的方法来计算 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
    

    【讨论】:

      【解决方案5】:

      您可以使用以前在普通查询中使用的标准方式,但在 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();
      

      【讨论】:

        猜你喜欢
        • 2013-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多