本文接著上篇文章Linq to SQL之使用預存程序 (1),繼續探討如何在Linq to SQL中使用預存程序。
在寫預存程序的時候,有時候會用到傳回值而不是output參數,現在看看怎樣取到該傳回值呢?
比如這樣一個預存程序:
create procedure dbo.linqDemo4 @input varchar(20)as select * from customers return 20
設計器自動產生的函數如下,可以看到並沒有提供方式取到該預存程序的傳回值:
[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; return (ISingleResult<Customer>)(result); }
增加一個out參數returnValue,這樣就能從結果中取到這個傳回值。不知道以後的設計器能不能自動識別。
有時候會到這種需求,預存程序返回多個結果集合,那麼這時候怎麼操作才能把結果集分開呢。比如下面這個預存程序,能不能把Customer和Order的結果集分別取到呢?
create procedure dbo.linqDemo5as select * from customers select * from orders
通過設計器來映射預存程序,不能識別多個結果集。如果自動建立結果類的話,它只識別出第一個返回的結果集,比如上面這個預存程序,自動產生的結果類
linqDemo5Result裡面只包括customer表的所有欄位。不過,Linq to SQL中提供了ResultType Attribute來標誌該預存程序會返回什麼類型的對象以及IMultipleResults介面來滿足獲得多個結果集的問題。首先看看自動產生的方法:
[Function(Name="dbo.linqDemo5")] public ISingleResult<linqDemo5Result> linqDemo5() { IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod()))); return ((ISingleResult<linqDemo5Result>)(result.ReturnValue)); }
我們對它進行修改,用ResultType標記返回的結果中將包含哪些類型,再使用IMultipleResults返回多個結果集
[Function(Name="dbo.linqDemo5")] [ResultType(typeof(Customer))] [ResultType(typeof(Order))] public IMultipleResults linqDemo5() { return (IMultipleResults)(this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())))).ReturnValue; }
在我們的代碼中如下使用:
NorthwindDataContext ctx = new NorthwindDataContext(); IMultipleResults results = ctx.linqDemo5(); foreach (var c in results.GetResult<Customer>()) { Console.WriteLine(c); } foreach (var o in results.GetResult<Order>()) { Console.WriteLine(o); }
值得注意的是GetResult的順序依賴於預存程序中返回結果的順序,如果先返回customer結果集就必須先調用GetResult<Customer>,否則會出現異常。可以說在調用GetResult的時候,根據對象屬性對應列來取值,一旦發現不匹配就會出現錯誤。假設裡面使用的dataReader,構造Customer對象的時候對屬性進行賦值,c.CustomerID=reader["CustomerID"],如果沒有這一列就拋出異常了。所以說在預存程序中使用多個結果集限制性非常大。