web-dev-qa-db-fra.com

Obtention de la valeur de retour d'une procédure stockée dans ADO.NET

Je sais qu'il existe une autre question portant à peu près le même titre, mais elle ne répond pas à ma question ..__ J'ai une procédure stockée, qui renvoie l'identificateur unique après l'insertion (@@ identity). Je l'ai essayé dans l'explorateur de serveur et cela fonctionne comme prévu (@RETURN_VALUE = [identificateur]) . Dans mon code, j'ai ajouté un paramètre appelé "@RETURN_VALUE", avec la direction ReturnValue en premier, que tout autre paramètre, mais quand je exécuter ma requête avec ExecuteNonQuery (), ce paramètre reste vide. Je ne sais pas ce que j'ai fait de mal… .. Mon 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

Et mon code est:

                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;
16
WebMonster

Juste essayé sur ma boîte et cela fonctionne pour moi:

Dans SQL Server:

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

En 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);
            }
        }
26
Florian Reischl

J'ai résolu le problème: vous devez définir SqlCommand.CommandType sur CommandType.StoredProcedure pour obtenir les valeurs de retour et/ou les paramètres de sortie. Je n'ai trouvé aucune documentation à ce sujet, mais maintenant tout fonctionne.

4
WebMonster

Avez-vous la valeur EXEC dans TSQL? Je me demande si le refactoring de TSQL pourrait aider (et utiliser SCOPE_IDENTITY():

alors changez:

COMMIT TRAN T1
RETURN @@IDENTITY

à:

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

(Je voudrais aussi changer l'autre @@IDENTITY en SCOPE_IDENTITY())


En guise d’optimisation mineure, vous pouvez également utiliser:

return (int)retval.Value;

mais ce côté des choses devrait aurait travaillé "tel quel" d'après ce que je peux voir (d'où la raison pour laquelle je me concentre sur TSQL).

3
Marc Gravell

Certains peuvent également utiliser cette méthode simple et courte pour calculer la valeur de retour de SP

En 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 renvoie toujours la valeur de type Int uniquement.

et en 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;
}

Vous pouvez également vérifier votre valeur de retour en SQL en utilisant cette commande:

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
1
Prashant Gupta

vous pouvez utiliser des méthodes standard que vous utilisiez auparavant dans les requêtes normales, mais dans la commande SQL, vous devez écrire EXEC avant le nom de votre procédure de stockage et ne pas utiliser le type de commande suivant:

 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();
0
dreamafon