預存程序的 RETURN 只能回傳 int,若需回傳字串或多值請改用 OUTPUT 參數。本文示範使用 SqlParameter 設定 Direction = ParameterDirection.ReturnValue 正確讀取返回值。
CREATE PROCEDURE GetOrderLine
@OrderId VARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM OrderLine WHERE OrderId = @OrderId;
RETURN 123; -- 僅能回傳 int
END
using (var conn = new SqlConnection(connStr))
using (var cmd = new SqlCommand("GetOrderLine", conn) { CommandType = CommandType.StoredProcedure })
{
// 輸入參數
cmd.Parameters.Add("@OrderId", SqlDbType.VarChar, 50).Value = "43c7cf15-6b2f-4d18-92b2-dbe827f30dfc";
// 返回值參數:務必設定 Direction = ReturnValue
var returnParam = cmd.Parameters.Add("@ReturnVal", SqlDbType.Int);
returnParam.Direction = ParameterDirection.ReturnValue;
conn.Open();
// 取得結果集
var dt = new DataTable();
using (var adapter = new SqlDataAdapter(cmd))
{
adapter.Fill(dt);
}
// 讀取 RETURN 值(必須在讀完結果集/關閉 DataReader 後)
int returnCode = (int)returnParam.Value;
Console.WriteLine($"預存程序返回碼: {returnCode}"); // 123
// 處理結果集
foreach (DataRow row in dt.Rows)
{
Console.WriteLine($"{row["ProductId"]}:{row["ProductPrice"]}:{row["ProductCount"]}");
}
}
| 項目 | 說明 |
|---|---|
| 返回值型別 | 只能是 int,若嘗試回傳字串會拋出型別轉換例外。 |
| 參數名稱 | 名稱可任意(如 @ReturnVal, @Ret),關鍵在 Direction。 |
| 讀取時機 | 使用 SqlDataAdapter.Fill 會自動關閉 DataReader,之後才能正確讀取 returnParam.Value。若用 ExecuteReader,需先 reader.Close() 再讀返回值。 |
| 多結果集 | 若預存程序有多個 SELECT,Fill 會將第一個填入 DataTable,其餘忽略;需用 ExecuteReader + NextResult() 處理。 |
CREATE PROCEDURE GetOrderSummary
@OrderId VARCHAR(50),
@TotalAmount DECIMAL(18,2) OUTPUT,
@ItemCount INT OUTPUT
AS
BEGIN
SELECT @TotalAmount = SUM(Price * Qty), @ItemCount = COUNT(*)
FROM OrderLine WHERE OrderId = @OrderId;
RETURN 0; -- 成功碼
END
var totalParam = cmd.Parameters.Add("@TotalAmount", SqlDbType.Decimal);
totalParam.Direction = ParameterDirection.Output;
totalParam.Precision = 18; totalParam.Scale = 2;
var countParam = cmd.Parameters.Add("@ItemCount", SqlDbType.Int);
countParam.Direction = ParameterDirection.Output;
// ... 執行後 ...
decimal total = (decimal)totalParam.Value;
int count = (int)countParam.Value;
Add 後單獨設定。