Store Procedure,存儲過程。也是被別人寫過的東西。我習慣性先看別人都寫了點啥,然后才開始想看看自己還要寫點啥。那就先談談它與udf的區別吧。
在 Linq To Sql進階系列(四)User Define Function篇 中,我們提到了兩者的差別。比如Store Procedure支持多個rowset的,而udf不行。他們還有一些其他的差別。Store Procedure只能返回整型,而udf可以是其他類型,比如char等,除個別類型外,比如imager類型,是不可以做為udf的返回類型的。Store Procedure支持Out Parameter而udf沒有。
1, SingleResultSet
我們先來看這個sprocs.
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
Customers?By?City
]
????
--
?Add?the?parameters?for?the?stored?procedure?here
????(
@param1
?
NVARCHAR
(
20
))
AS
BEGIN
????
--
?SET?NOCOUNT?ON?added?to?prevent?extra?result?sets?from
????
--
?interfering?with?SELECT?statements.
????
SET
?NOCOUNT?
ON
;
????
SELECT
?CustomerID,?ContactName,?CompanyName,?City?
from
?Customers?
as
?c?
where
?c.City
=
@param1
END
其生成的code如下。
????????[Function(Name
=
"
dbo.[Customers?By?City]
"
)]
????????
public
?ISingleResult
<
Customers_By_CityResult
>
?Customers_By_City([Parameter(DbType
=
"
NVarChar(20)
"
)]?
string
?param1)
????????
{
????????????IExecuteResult?result?
=
?
this
.ExecuteMethodCall(
this
,?((MethodInfo)(MethodInfo.GetCurrentMethod())),?param1);
????????????
return
?((ISingleResult
<
Customers_By_CityResult
>
)(result.ReturnValue));
????????}
這里Customers_By_CityResult是這個sprocs的影射類。但你可以在OR Designer里調整。如圖,
選中該函數后,右擊屬性。就可以使用其他影射類。但是Linq會對返回的rowset做檢查,如果發現返回結果和影射不匹配它會報錯。而且一旦更改了,當你需要改回去的時候,你只能在Designer中刪掉此sprocs,然后重新拖過來。
調用它很簡單,就當作一個函數,但是,這里和普通的linq語句不一樣的地方是,它不是延遲加載的。
????????????DataClasses1DataContext?db?
=
?
new
?DataClasses1DataContext();
????????????db.Log?
=
?Console.Out;
????????????var?q?
=
?db.Customers_By_City(
"
London
"
);
正因它不是延遲加載的,所以,linq可以對他進行簡單的內聯操作,比如
????????????DataClasses1DataContext?db?
=
?
new
?DataClasses1DataContext();
????????????db.Log?
=
?Console.Out;
????????????var?q?
=
?from?c?
in
?db.Customers_By_City(
"
London
"
)
????????????????????orderby?c.City
????????????????????select?c;
注意的時,這里是Linq To Object而不是Linq To Sql。
2, MultipleResultSets
看下面的例子
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
Get?Customer?And?Orders
]
(
@CustomerID
?
nchar
(
5
))
????
--
?Add?the?parameters?for?the?stored?procedure?here
AS
BEGIN
????
--
?SET?NOCOUNT?ON?added?to?prevent?extra?result?sets?from
????
--
?interfering?with?SELECT?statements.
????
SET
?NOCOUNT?
ON
;
????
SELECT
?
*
?
FROM
?Customers?
AS
?c?
WHERE
?c.CustomerID?
=
?
@CustomerID
??
????
SELECT
?
*
?
FROM
?Orders?
AS
?o?
WHERE
?o.CustomerID?
=
?
@CustomerID
END
使用OR designer對其影射,其dbml為
??
<
Function?
Name
="dbo.[Get?Customer?And?Orders]"
?Method
="Get_Customer_And_Orders"
>
????
<
Parameter?
Name
="CustomerID"
?Parameter
="customerID"
?Type
="System.String"
?DbType
="NChar(5)"
?
/>
????
<
ElementType?
Name
="Get_Customer_And_OrdersResult"
>
??????
<
Column?
Name
="CustomerID"
?Type
="System.String"
?DbType
="NChar(5)?NOT?NULL"
?CanBeNull
="false"
?
/>
??????
<
Column?
Name
="CompanyName"
?Type
="System.String"
?DbType
="NVarChar(40)?NOT?NULL"
?CanBeNull
="false"
?
/>
??????
<
Column?
Name
="ContactName"
?Type
="System.String"
?DbType
="NVarChar(30)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ContactTitle"
?Type
="System.String"
?DbType
="NVarChar(30)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Address"
?Type
="System.String"
?DbType
="NVarChar(60)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="City"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Region"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="PostalCode"
?Type
="System.String"
?DbType
="NVarChar(10)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Country"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Phone"
?Type
="System.String"
?DbType
="NVarChar(24)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Fax"
?Type
="System.String"
?DbType
="NVarChar(24)"
?CanBeNull
="true"
?
/>
????
</
ElementType
>
??
</
Function
>
用sqlmetal對它做影射,生成dbml為
<
Function?
Name
="dbo.Get?Customer?And?Orders"
?Method
="GetCustomerAndOrders"
>
????
<
Parameter?
Name
="CustomerID"
?Parameter
="customerID"
?Type
="System.String"
?DbType
="NChar(5)"
?
/>
????
<
ElementType?
Name
="GetCustomerAndOrdersResult1"
>
??????
<
Column?
Name
="CustomerID"
?Type
="System.String"
?DbType
="NChar(5)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="CompanyName"
?Type
="System.String"
?DbType
="NVarChar(40)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ContactName"
?Type
="System.String"
?DbType
="NVarChar(30)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ContactTitle"
?Type
="System.String"
?DbType
="NVarChar(30)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Address"
?Type
="System.String"
?DbType
="NVarChar(60)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="City"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Region"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="PostalCode"
?Type
="System.String"
?DbType
="NVarChar(10)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Country"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Phone"
?Type
="System.String"
?DbType
="NVarChar(24)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Fax"
?Type
="System.String"
?DbType
="NVarChar(24)"
?CanBeNull
="true"
?
/>
????
</
ElementType
>
????
<
ElementType?
Name
="GetCustomerAndOrdersResult2"
>
??????
<
Column?
Name
="OrderID"
?Type
="System.Int32"
?DbType
="Int"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="CustomerID"
?Type
="System.String"
?DbType
="NChar(5)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="EmployeeID"
?Type
="System.Int32"
?DbType
="Int"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="OrderDate"
?Type
="System.DateTime"
?DbType
="DateTime"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="RequiredDate"
?Type
="System.DateTime"
?DbType
="DateTime"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShippedDate"
?Type
="System.DateTime"
?DbType
="DateTime"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipVia"
?Type
="System.Int32"
?DbType
="Int"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="Freight"
?Type
="System.Decimal"
?DbType
="Money"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipName"
?Type
="System.String"
?DbType
="NVarChar(40)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipAddress"
?Type
="System.String"
?DbType
="NVarChar(60)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipCity"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipRegion"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipPostalCode"
?Type
="System.String"
?DbType
="NVarChar(10)"
?CanBeNull
="true"
?
/>
??????
<
Column?
Name
="ShipCountry"
?Type
="System.String"
?DbType
="NVarChar(15)"
?CanBeNull
="true"
?
/>
????
</
ElementType
>
??
</
Function
>
仔細比較他們的區別哦。“好像名字不一樣呢”。暈倒。看主要的。第一個只有一個ElementType子項,而第二個有2個。這個地方其實可以說是OR designer的一個bug。要想修改這個bug,需要更改一個設計,而推動更改設計,比較麻煩。但并不是不能改。如果你認為這個真的很需要,而且對你很重要,你更喜歡用or designer的話,我建議你去下面的社區發帖子。
http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=123&SiteID=1
要求更改此處的問題。因為,我已經無力推動他們修復該bug,ms更樂意聽來自客戶的聲音,說不定你會成功的哦,還有獎勵的哦。
這個sprocs準確的影射代碼為
????????[Function(Name
=
"
dbo.Get?Customer?And?Orders
"
)]
????????[ResultType(
typeof
(GetCustomerAndOrdersResult1))]
????????[ResultType(
typeof
(GetCustomerAndOrdersResult2))]
????????
public
?IMultipleResults?GetCustomerAndOrders([Parameter(Name
=
"
CustomerID
"
,?DbType
=
"
NChar(5)
"
)]?
string
?customerID)
????????
{
????????????IExecuteResult?result?
=
?
this
.ExecuteMethodCall(
this
,?((MethodInfo)(MethodInfo.GetCurrentMethod())),?customerID);
????????????
return
?((IMultipleResults)(result.ReturnValue));
????????}
對于MultipleResultSets的sprocs,大家更關注如何取其返回結果。其實很簡單,按順序,一個rowset,一個rowset的取。這個順序和你sprocs里的順序是一樣的。
IMultipleResults result = db.GetCustomerAndOrders("SEVES");
IEnumerable<CustomerResultSet> customer = result.GetResult<CustomerResultSet>();
IEnumerable<OrdersResultSet> orders = result.GetResult<OrdersResultSet>();
如果,你很貪心,再加一行的話,
IEnumerable<CustomerResultSet> customer = result.GetResult<CustomerResultSet>();
報錯咯,越界了。沒有那么多,你問要也不給。
3,OutParameters
似乎沒有什么好講的,很簡單,當作ref 的函數參數輸出的。其也只是在生成的函數里加了這么一句
outParameter = ?((System. Nullable < int >)(result.GetParameterValue(1))); 調用result.GetParameterValue方法,大家要記住這個哦。
4,Return Value
呀,把return value丟那里了。的確,Linq曾舍棄過return value.后來在qa的堅持下,dev們決定保留了它。但是,需要你自己去更改code,才能獲得。我們可以從下面這個sprocs上獲得靈感。
CREATE
?
PROCEDURE
?
[
dbo
]
.
[
CustOrderTotal
]
?
@CustomerID
?
nchar
(
5
),
@TotalSales
?
money
?OUTPUT
AS
SELECT
?
@TotalSales
?
=
?
SUM
(OD.UNITPRICE
*
(
1
-
OD.DISCOUNT)?
*
?OD.QUANTITY)
FROM
?ORDERS?O,?"
ORDER
?DETAILS"?OD
where
?O.CUSTOMERID?
=
?
@CustomerID
?
AND
?O.ORDERID?
=
?OD.ORDERID
其影射的code為
????????[Function(Name
=
"
dbo.CustOrderTotal
"
)]
????????
public
?
int
?CustOrderTotal([Parameter(Name
=
"
CustomerID
"
,?DbType
=
"
NChar(5)
"
)]?
string
?customerID,?[Parameter(Name
=
"
TotalSales
"
,?DbType
=
"
Money
"
)]?
ref
?System.Nullable
<
decimal
>
?totalSales)
????????
{
????????????IExecuteResult?result?
=
?
this
.ExecuteMethodCall(
this
,?((MethodInfo)(MethodInfo.GetCurrentMethod())),?customerID,?totalSales);
????????????totalSales?
=
?((System.Nullable
<
decimal
>
)(result.GetParameterValue(
1
)));
????????????
return
?((
int
)(result.ReturnValue));
????????}
因為該sprocs并沒有rowset返回,其最后只剩返回值了。其是將result.RenturnValue強制轉化為int型,以得到sprocs的整形返回值。那對于SingleResultSet和MultipleResultSets的,該如何獲取它的返回值呢?那只有自己動手,修改code了。就是自己強制轉換,而后通過out 參數輸出。比如用第一個sprocs
????????[Function(Name?
=
?
"
dbo.[Customers?By?City]
"
)]
????????
public
?ISingleResult
<
Customers_By_CityResult1
>
?Customers_By_City([Parameter(DbType?
=
?
"
NVarChar(20)
"
)]?
string
?param1)
????????
{
????????????IExecuteResult?result?
=
?
this
.ExecuteMethodCall(
this
,?((MethodInfo)(MethodInfo.GetCurrentMethod())),?param1);
????????????
return
?((ISingleResult
<
Customers_By_CityResult1
>
)(result.ReturnValue));
????????}
????????
public
?ISingleResult
<
Customers_By_CityResult1
>
?Customers_By_City2(
string
?para,?
out
?
int
?returnValue)
????????
{
????????????ISingleResult
<
Customers_By_CityResult1
>
?result?
=
?
this
.Customers_By_City(para);
????????????returnValue?
=
?(
int
)result.ReturnValue;
????????????
return
?((ISingleResult
<
Customers_By_CityResult1
>
)result);
????????}
測試一下
????????????DataClasses1DataContext?db?
=
?
new
?DataClasses1DataContext();
????????????db.Log?
=
?Console.Out;
????????????
int
?returnValue?
=
?
-
1
;
????????????var?q?
=
?db.Customers_By_City2(
"
London
"
,
out
?returnValue);
????????????Console.WriteLine(returnValue);
也可以使用result.GetParameterValue方法獲取返回值。只是linq會檢查影射函數的參數個數。這個使用起來比較麻煩。可以這么使用,比如,有一個sprocs,有2個參數,其中有一個out的參數。這個out的參數,可以不做任何操作。在影射后,修改其code。這兩個參數的位標是從0開始,依次遞增。其code本來為outParameter = ?((System.
Nullable
<
int
>)(result.GetParameterValue(1))); 將其索引修改位為2,就是return value了。再大了又該拋了。
ps:招聘,我就趁機打個廣告吧.呵呵。赴微軟測試工程師
1, 計算機或軟件,相關專業,本科或碩士以上。
2, 2年及2年以上工作經驗。
3, 英語,聽說讀寫流利。
4, 工作認真負責,學習能力強。
5, 精通c#1.1及c#2.0版本語言,對c#3.0有了解。
6, 精通算法。
7, 有Ado.Net 和Asp.Net的經驗。技術好。
有意者投簡歷到 guoan@126.com ?謝謝
相關文章:
ps:
C# 3.0 入門系列(一)
C# 3.0入門系列(二)
C# 3.0入門系列(三)
C# 3.0入門系列(四)-之Select操作
C#3.0入門系列(五)-之Where操作
C#3.0入門系列(六)-之OrderBy操作
C#3.0入門系列(七)--之OR工具介紹
C#3.0入門系列(八)-之GroupBy操作
C#3.0入門系列(九)-之GroupBy操作
C#3.0入門系列(十)-之Join操作
C#3.0入門系列(十一)-之In, Like操作
C#3.0入門系列(十二)-Lambda表達式中Lifting
Linq To Sql進階系列(一)-從映射講起
Linq To Sql進階系列(二)M:M關系
Linq To Sql進階系列(三)CUD和Log
Linq To Sql進階系列(四)User Define Function篇
Linq To Sql進階系列(五)Store Procedure篇
TrackBack: http://www.cnblogs.com/126/archive/2007/08/16/851138.html
在 Linq To Sql進階系列(四)User Define Function篇 中,我們提到了兩者的差別。比如Store Procedure支持多個rowset的,而udf不行。他們還有一些其他的差別。Store Procedure只能返回整型,而udf可以是其他類型,比如char等,除個別類型外,比如imager類型,是不可以做為udf的返回類型的。Store Procedure支持Out Parameter而udf沒有。
1, SingleResultSet
我們先來看這個sprocs.

















選中該函數后,右擊屬性。就可以使用其他影射類。但是Linq會對返回的rowset做檢查,如果發現返回結果和影射不匹配它會報錯。而且一旦更改了,當你需要改回去的時候,你只能在Designer中刪掉此sprocs,然后重新拖過來。
調用它很簡單,就當作一個函數,但是,這里和普通的linq語句不一樣的地方是,它不是延遲加載的。









2, MultipleResultSets
看下面的例子


























































http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=123&SiteID=1
要求更改此處的問題。因為,我已經無力推動他們修復該bug,ms更樂意聽來自客戶的聲音,說不定你會成功的哦,還有獎勵的哦。
這個sprocs準確的影射代碼為








對于MultipleResultSets的sprocs,大家更關注如何取其返回結果。其實很簡單,按順序,一個rowset,一個rowset的取。這個順序和你sprocs里的順序是一樣的。
IMultipleResults result = db.GetCustomerAndOrders("SEVES");
IEnumerable<CustomerResultSet> customer = result.GetResult<CustomerResultSet>();
IEnumerable<OrdersResultSet> orders = result.GetResult<OrdersResultSet>();
如果,你很貪心,再加一行的話,
IEnumerable<CustomerResultSet> customer = result.GetResult<CustomerResultSet>();
報錯咯,越界了。沒有那么多,你問要也不給。
3,OutParameters
似乎沒有什么好講的,很簡單,當作ref 的函數參數輸出的。其也只是在生成的函數里加了這么一句
outParameter = ?((System. Nullable < int >)(result.GetParameterValue(1))); 調用result.GetParameterValue方法,大家要記住這個哦。
4,Return Value
呀,把return value丟那里了。的確,Linq曾舍棄過return value.后來在qa的堅持下,dev們決定保留了它。但是,需要你自己去更改code,才能獲得。我們可以從下面這個sprocs上獲得靈感。

































ps:招聘,我就趁機打個廣告吧.呵呵。赴微軟測試工程師
1, 計算機或軟件,相關專業,本科或碩士以上。
2, 2年及2年以上工作經驗。
3, 英語,聽說讀寫流利。
4, 工作認真負責,學習能力強。
5, 精通c#1.1及c#2.0版本語言,對c#3.0有了解。
6, 精通算法。
7, 有Ado.Net 和Asp.Net的經驗。技術好。
有意者投簡歷到 guoan@126.com ?謝謝
相關文章:
ps:
C# 3.0 入門系列(一)
C# 3.0入門系列(二)
C# 3.0入門系列(三)
C# 3.0入門系列(四)-之Select操作
C#3.0入門系列(五)-之Where操作
C#3.0入門系列(六)-之OrderBy操作
C#3.0入門系列(七)--之OR工具介紹
C#3.0入門系列(八)-之GroupBy操作
C#3.0入門系列(九)-之GroupBy操作
C#3.0入門系列(十)-之Join操作
C#3.0入門系列(十一)-之In, Like操作
C#3.0入門系列(十二)-Lambda表達式中Lifting
Linq To Sql進階系列(一)-從映射講起
Linq To Sql進階系列(二)M:M關系
Linq To Sql進階系列(三)CUD和Log
Linq To Sql進階系列(四)User Define Function篇
Linq To Sql進階系列(五)Store Procedure篇
TrackBack: http://www.cnblogs.com/126/archive/2007/08/16/851138.html
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
