LINQ to SQL系列Part 6 - Retrieving Data Using Stored Procedures

 LINQ to SQL系列Part 6 - Retrieving Data Using Stored Procedures
本文轉載自:
http://www.cnblogs.com/hanxianlong/archive/2007/11/25/967630.html

英文原貼鏈接:
http://weblogs.asp.net/scottgu/archive/2007/08/16/linq-to-sql-part-6-retrieving-data-using-stored-procedures.aspx

在這前五篇帖子中,我說明了如何用LINQ的查詢表達式通過編程的方式從數據庫中檢索數據。在今天的帖子中,我將會講述一下如何和LINQ to SQL 數據模型一起來使用數據庫中的存儲過程(SPROCs)和自定義的函數(UDFs)。今天的博客會具體地講一下如何調用存儲過程從數據庫中查詢和檢索數據庫。在本系列的下五篇帖子中,我講會講一下如何選擇用存儲過程來更新/插入/刪除數據。


使用存儲過程還是不使用?這是個問題....

在建立數據層時是使用ORM生成的動態SQL語句還是用存儲過程這個問題在開發者,架構師和DBA之間一直爭論不休。許多比我聰明的人已經寫過此話題, 所以在此我不想重複地談論是贊成還是反對這個問題。

在.NET 3.5中的LINQ to SQL ORM非常靈活,你可以用來生成數據模型類,該數據模型類可以獨立於數據庫中的數據結構,而且可以寫入無論是使用動態生成的SQL還是存儲過程都可以執行的業務邏輯和驗證規則。

在第3部分LINQ to SQL Part 3: Querying our Database:查詢數據庫這篇帖子中,我討論瞭如何對LINQ to SQL數據模型像下面這樣寫LINQ的查詢表達式:

圖1

當你像這樣寫LINQ 查詢表達式時,LINQ to SQL 模型將會執行必要的動態SQL語句來檢索出跟你的查詢匹配的產品對象。

在這篇帖子中你將學到,你也可以選擇將數據庫中的存儲過程遇到到你的LINQ to SQL DataContext類中,存儲過程會允許你調用它來完成對產品對象的檢索功能。

圖2 

這種數據模型的既能調用動態SQL又能調用存儲過程能力是非常強大的,並且在對對象的操作上它提供了強大的靈活性。

在LINQ to SQL中映射和調用存儲過程的步驟
 

在第二部分我講述瞭如何用LINQ to SQL ORM設計器來生成一個如下的LINQ to SQL類模型:


 圖3

注意,在上邊的LINQ to SQL ORM設計器中有兩個面板。左側的面板使我們可以定義映射到我們數據庫的數據模型。右側的面板允許我們有選擇的映射存儲過程(和自定義的函數)到我們的LINQ to sQL DataContexxt對象,這個映射的存儲過程可以允許我們用它來代替動態生成的SQL語句來從該數據模型對象中查找數據。

如何將存儲過程映射到LINQ to SQL DataContext

爲了映射存儲過程到我們的DataContext類中,讓我們產生到VS2008中的Server Explorer窗口,看一下在數據庫中的存儲過程:
 
 

圖4

我們可以雙擊存儲過程來打開和編輯它們,例如,下面是在Northwind中的“CustOrderHist"的存儲過程:

圖5

爲了將上面的存儲過程映射到我們的LINQ to SQL DataContext中,我們通過用拖放的方式將它從Server Explorer中拖到我們的LINQ to SQL ORM設計器中。這將自動地在LINQ to SQL DataContext類中生成如下的一個新方法:
 

 圖6
 
默認情況下,在DataContext爲上生成的這個方法的方法名是和存儲過程的名稱是一樣的,並且這個方法的返回值類型的命名方式是“[存儲過程名稱]結果”。例如,上面的存儲過程將會返回一個"CustOrderHistResult"對象序列。我們可以選擇將這個方法名進行更改:在設計器上選中它,用屬性窗口來對它進行重命名。

如何調用我們新映射的存儲過程

做完了上面的映射存儲過程到我們的DataContext類的第一步之後,用它來進行編程的方式進行檢索數據就很容易了。我們所做的只是來調用映射到我們的DataContext類上的方法來獲取從存儲過程中返回的一個強類型的序列。

在VB中調用存儲過程:

 圖7
 在C#中調用存儲過程:

 

圖8
 

除了像上面那樣對結果集進行遍歷之外,我還可以將結果集綁定到UI上並將它們顯示出來。例如,下面的代碼將我們的存儲過程的結果集綁定到了<asp:gridview>控件上:
 
 

圖9


在網頁上它就會顯示出我們客戶的產品歷史記錄:

 
 圖10

將存儲過程的返回值類型映射到數據模型類上

在上面的"CustOrderHist"例子中,存儲過程返回的是一個產品歷史記錄的序列,這個結果包含了兩列數據:Product的ProuctName,客戶對那條產品記錄下的訂單記錄的總數。LINQ to SQL設計器自動地定義了一個"CustOrderHistResult"類來展示該結果。存儲過程映射到了一個我們已經在LINQ to sQL設計器中定義好的數據模型類中(例如,一個已經存在的Product或者Order實體類)。例如,假設在數據庫中我們有一個"GetProductByCategory"存儲過程,它返回如下的產品信息:

 
 圖11
 

像以前那樣,我們通過拖放的方式將存儲過程拖到我們的LINq to sql 設計器上來在我們的DataContext中生成一個"GetProductsByCategory"方法。這次不是將這個存儲過程拖到設計器任意位置,而是將它拖到在數據模型設計器中已經存在的“Product"類上:
 
 

圖12

將存儲過程拖到Product類上的這種行爲就告訴了linq to sql 設計器,使"GetProductCategory"方法的返回一個“Product"對象:
 

圖13

將我們的存儲過程像上面那樣讓它返回一個"Product"對象的其中一個非常酷的事情是:linq to sql 將會像跟蹤通過linq 查詢返回的產品對象那樣自動跟蹤的通過該存儲過程返回的product對象的變化。當我們調用這個DataContext類上的"SubmitChanges()"方法時,我們對該對象所做的任何的變動將會自動地被保存回數據庫中。例如,我們可以寫如下的代碼來(用存儲過程)檢索數據,並且將某一類別的所有產品的價格變爲當前值的90%:

 

圖14
 

在最後調用SubmitChange()方法是,它就會自動地通過調用事務對所有的產品的價格進行更新。若想學習更多的關於如何跟蹤變化和SubmitChanges()是如何工作的,如何將驗證業務邏輯添加到我們的數據模型實體是,請閱讀我的第四部分(LINQ to SQL Part 4: Updating our Database)。

 在本系列的的下一篇博客中,我也會講解如何用自定義的存儲過程代替動態生成的插入、更新、刪除的sql語句來處理數據庫的更新。上面代碼比較好的一點是,如果我將我的DataContext配置爲用存儲過程進行更新--那麼它就會是一個純粹的在映射層的變化,並且對我的數據模型所寫的代碼不會注意到它。

處理存儲過程的輸出參數

將存儲過程中的輸出參數映射爲了一個引用參數(ref keyword),對於值類型的,將參數聲明爲了可空(nullable)類型。 例如,看一下下面的這個存儲過程"GetCustomerDetails",該存儲過程將CustomerID作爲輸入參數,查詢的返回值是該Customer的訂單歷史以及它的將公司名作爲輸出參數:

圖15
 
 如果我們將上面的存儲過程拖到我們的“Order"類上,我們就可以通過寫如下的代碼來調用它:

VB: 
 

圖16
 

C#: 
 

圖17
 

注意上面的代碼,存儲過程助手方法是如何幫助一個產品對象序列的,並且也將CompanyName作爲一個輸出參數返回給助手方法。

處理存儲過程返回的多種返回結果

當一個存儲過程可能返回多種結果集是,該在DataContext中的存儲過程方法就不可以聲明爲某單一一種類型的強返回值類型了。例如,看一下如下的存儲過程,它根據輸出參數的不同可能會返回一個產品結果集,也可以返回一個訂單結果集。

  圖18

linq to sql 支持生成一個存儲過程助手方法來執行該存儲過程並且返回一個如下的IMultipleReulst對象,該方法可以通過向項目中添加一個"NorthwindDataContext"類來返回Product或者是Order類型:
VB:

 圖19

C#: 
 

圖20
 

一旦我們該方法添加到我們的項目中,當我們使用的時候就可以調用它並且將結果集或者轉換爲Product或者是Order序列:

VB: 
 

圖21
 

C#: 
 

 圖22
 

對用戶自定義函數的支持

除了支持存儲過程,linq to sql 也支持scalar-valued和table-valued的用戶自定義函數,存儲過程和自定義函數是地位相等同的。一旦將自定義函數作爲方法添加到了你的DataContext中,你就可以在linq 查詢中使用它們了。例如,看一下下面這個簡單的用戶自定義函數"MyUpperFunction":

圖23

我們可以通過將它從VS Server Explorer中拖到linq to sql 設計器中,作爲我們的DataContext上的一個方法添加進來:
 
 

圖24

當對該linq to sql數據模型來寫linq 表達式時,我們就可以用linq表達式來調用該自定義函數(注意它在下面的"where"語句中使用到了):
VB:

  

圖25

C#:

 圖26

 如果你用到了我在博客中(here)說的LINQ to SQL Debug Visualizer,在運行時你就可以看到linq to sql 是如何將上面的表達式轉換爲原生的sql語句來在數據庫中執行自定義的函數的:
   

圖27


總結

linq to sql 支持調用數據庫中的存儲過程和自定義函數,並且能夠很好地將它們和我們的數據庫模型進行集成。在這篇博客中我講述瞭如何通過調用存儲過程來方便地檢索數據並且從數據模型類中取出我們需要的數據來。在下本系列的下一篇博客中,我將會講解在調用SubmitChanges()方法將變動保存至數據庫中時,如何調用存儲過程來替代更新、插入、刪除邏輯。

Scott

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章