承接上篇《LINQ to SQL 存儲程序基礎映射》,本文探討兩個實務常見進階場景:擷取存儲程序整數回傳值 以及 處理多結果集。
SQL Server 存儲程序可用 RETURN @intValue 回傳狀態碼 (0=成功, -1=失敗等)。但 LINQ to SQL 設計器產生的方法預設僅回傳 ISingleResult<T>,**不直接暴露 RETURN 值**。
CREATE PROCEDURE dbo.linqDemo4
@input VARCHAR(20)
AS
BEGIN
SELECT * FROM Customers;
RETURN 20; -- 回傳狀態碼
END
[Function(Name="dbo.linqDemo4")]
public ISingleResult<Customer> linqDemo4(
[Parameter(DbType="VarChar(20)")] string input)
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())), input);
return ((ISingleResult<Customer>)(result.ReturnValue));
}
public ISingleResult<Customer> linqDemo4WithReturnValue(
string input, out int returnValue)
{
ISingleResult<Customer> result = linqDemo4(input);
returnValue = (int)result.ReturnValue; // 關鍵:IExecuteResult.ReturnValue 即為 SP RETURN 值
return result;
}
呼叫端:
int spReturnCode;
var customers = ctx.linqDemo4WithReturnValue("test", out spReturnCode);
Console.WriteLine($"SP 回傳碼: {spReturnCode}"); // 輸出 20
💡 未來設計器版本或可自動識別並產生 out int returnValue 參數。
若存儲程序包含多條 SELECT,預設設計器僅映射第一個結果集,且產生匿名結果類別 (linqDemo5Result)。
CREATE PROCEDURE dbo.linqDemo5
AS
BEGIN
SELECT * FROM Customers; -- 結果集 1
SELECT * FROM Orders; -- 結果集 2
END
[Function(Name="dbo.linqDemo5")]
public ISingleResult<linqDemo5Result> linqDemo5()
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())));
return ((ISingleResult<linqDemo5Result>)(result.ReturnValue));
}
[Function(Name="dbo.linqDemo5")]
[ResultType(typeof(Customer))] // 聲明第 1 個結果集型別
[ResultType(typeof(Order))] // 聲明第 2 個結果集型別
public IMultipleResults linqDemo5()
{
return (IMultipleResults)(this.ExecuteMethodCall(this,
((MethodInfo)(MethodInfo.GetCurrentMethod())))).ReturnValue;
}
var ctx = new NorthwindDataContext();
IMultipleResults results = ctx.linqDemo5();
// ⚠️ 順序必須與 SP 中 SELECT 順序一致
foreach (var c in results.GetResult<Customer>())
Console.WriteLine($"Customer: {c.CustomerID}");
foreach (var o in results.GetResult<Order>())
Console.WriteLine($"Order: {o.OrderID}");
GetResult<T>() 呼叫順序必須與存儲程序 SELECT 順序完全一致,否則會因欄位對應失敗拋出例外。DataReader 依欄位名稱映射屬性,SELECT * 若資料表結構變更極易出錯,建議明確列出欄位。掌握 IExecuteResult.ReturnValue 擷取回傳碼、[ResultType] + IMultipleResults 處理多結果集,能讓 LINQ to SQL 在存儲程序整合上應對更複雜的實務需求。但請謹記:多結果集映射脆弱且限制多,**能拆分為多個存儲程序或改用 Table-Valued Parameters / JSON 輸出時,優先考慮替代方案**。