Я знаю, что существует другой вопрос почти с тем же заголовком, но он не отвечает на мой вопрос. У меня есть хранимая процедура, которая возвращает уникальный идентификатор после вставки (@@ идентификационные данные). Я попробовал его в проводнике сервера, и это работает как ожидалось (@RETURN_VALUE = [идентификатор]). В моем коде я добавил параметр, названный "@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
, чтобы получить возвращаемые значения и/или выходные параметры. Я не нашел никакой документации об этом, но теперь все работает.
Получаете ли вы значение своего EXEC
в TSQL? Интересно, поможет ли рефакторинг TSQL (и использование SCOPE_IDENTITY ()
:
, поэтому измените:
COMMIT TRAN T1
RETURN @@IDENTITY
на:
SET @auctionID = SCOPE_IDENTITY()
COMMIT TRAN T1
RETURN @auctionID
(я бы также изменил другой @@ IDENTITY
] to SCOPE_IDENTITY ()
)
В качестве небольшой оптимизации вы также можете использовать:
return (int)retval.Value;
но эта сторона вещей должна была работать "как есть", насколько я могу см. (поэтому я сосредотачиваюсь на TSQL).