2010-07-22 11 views
16

So che c'è un'altra domanda con quasi lo stesso titolo, ma non risponde alla mia domanda. Ho una stored procedure, che restituisce l'identificatore univoco dopo l'inserimento (@@ identity). L'ho provato nel server explorer e funziona come previsto (@RETURN_VALUE = [identificatore]). Nel mio codice ho aggiunto un parametro chiamato "@RETURN_VALUE", con la direzione ReturnValue prima di qualsiasi altro parametro, ma mentre eseguo la mia query con ExecuteNonQuery() quel parametro rimane vuoto. Non so cosa ho fatto di sbagliato. mio SPROC:Ottenere il valore di ritorno dalla stored procedure in ADO.NET

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 

E il mio codice è:

   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; 
+0

Quando dici "vuoto" - stai ricevendo un'eccezione dicendo che "Valore" è nullo? (Il cast fallirebbe se fosse nullo). O è 0? –

+0

Il valore è 0. – WebMonster

+4

BTW, '@@ IDENTITY' è pericoloso; dovresti usare 'SCOPE_IDENTITY()'. –

risposta

22

appena provato sulla mia casella e questo funziona per me:

In SQL Server:

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

In 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); 
      } 
     } 
+0

id get è il valore 0. – WebMonster

+0

Ho esteso l'esempio. Forse lo proverai. –

3

si ottiene il valore di voi EXEC in TSQL? Mi chiedo se il refactoring del TSQL avrebbe aiutato (e usando SCOPE_IDENTITY():

quindi cambiare:

COMMIT TRAN T1 
RETURN @@IDENTITY 

a:

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

(vorrei anche cambiare l'altro @@IDENTITY a SCOPE_IDENTITY())


Come ottimizzazione minore, si potrebbe anche usare:

return (int)retval.Value; 

ma questo lato delle cose dovrebbe hanno lavorato "come è" da quello che posso vedere (da qui il motivo per cui mi sto concentrando sulla TSQL).

+0

Modificato cosa hai suggerito, ma nessun effetto. Io uso "EXEC SetAuction @auctionID, ..." come CommandText. Ottengo il valore restituito se lo eseguo da server explorer (Visual Studio). – WebMonster

4

ho risolto il problema: è necessario impostare SqlCommand.CommandType a CommandType.StoredProcedure per ottenere valori di ritorno e/o parametri di uscita. Non ho trovato alcuna documentazione al riguardo, ma ora tutto funziona.

1

Qualcuno può anche utilizzare questo metodo semplice e breve per calcolare il valore di ritorno dalla SP

In 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 restituisce sempre Int valore di tipo solo.

e in 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; 
} 

È inoltre possibile controllare il tuo valore di ritorno in SQL utilizzando questo comando:

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 
0

è possibile utilizzare modi standart che si utilizza, prima nelle query normali, ma nel comando Sql è necessario scrivere EXEC prima del nome della procedura di archiviazione e non utilizzare il comando tipo come segue:

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(); 
Problemi correlati