LINQ to SQL系列Part 8 - Using LINQ to SQL
本文轉載自:
http://www.cnblogs.com/hanxianlong/archive/2007/12/07/987205.html
在前兩篇帖子中 (Part 6 and Part 7)我描述瞭如何用LINQ to SQL數據模型通過數據庫的存儲過程和用戶自定義的函數來查詢和檢索數據。
在今天的博客中我將討論一下如何選擇使用存儲過程來更新、插入、刪除數據。
自從我寫了那些帖子之後,許多人問我的問題之一就是“如果我想完全控制linq to sql的sql表達式,並且我又不想用存儲過程--我該怎麼做?”今天的博客將會講述這個問題--並且討論一下如何使用自定義的sql表達式來控制你的linq to sql 數據模型類,對其插入、更新和刪除。
和LINQ to SQL一起使用LINQ查詢表達式
爲了完成今天帖子要講述的內容,讓我們假設已經用VS2008中的LINQ to SQL ORM設計器爲Northwind數據庫定義一個如下的數據模型類:(在本系列的第2部分Part 2 中講述瞭如何用設計器定義此數據模型類):
圖1
在本系列的第3部分(Part 3),我講述瞭如何用在VB和C#中支持的新的LINQ語言來對上面的數據模型類進行查詢,並且返回一個代表了數據庫中的行/列關係的對象。
例如,我們可以向我們的數據模型的DataContext類中添加一個"GetProductsByCategory"的幫助方法 ,該方法用LINQ查詢從數據庫中進行查詢並返回一個Product對象集合:
VB:
圖2
C#:
圖3
一旦我們定義了LINQ幫助方法,我們可以寫如下的代碼,用LINQ的幫助方法來檢索產品並且對結果進行遍歷:
VB:
圖4
當"GetProductsByCategory"方法被調用時, LINQ to SQL ORM將會運行動態的SQL來檢索產品數據。你可以在LINQ to SQL Debug Visualizer中查看這個LINQ表達式最終是如何生成的。
和LINQ to SQL一起使用自定義的SQL查詢
在上面的例子中,我們沒有寫任何的SQL代碼來查詢數據庫和檢索出強類型的產品對象。取代之的是,linq to sql orm會自動的將linq表達式翻譯爲sql語句,並且使用生成的sql語句對數據庫進行操作。
可是,若是我們想完全控制對我們的數據庫進行操作的sql語句,並且不想讓linq to sql爲我們自動生成的話,該怎麼做呢?實現這個目的的方法之一是使用在本系列的第 六(Part 6)和第七( Part 7)部分講解的存儲過程。另外一個方法是使用在DataContext基類中的"ExecuteQuery"幫助方法,使用我們提供的自定義的sql表達式。
使用ExecuteQuery方法
ExecuteQuery方法將sql查詢表達式作爲參數,和一系列的我們可以選擇使用參數列表。使用這一功能我們可以對數據庫執行原始的sql語句(包括自定義的多表之間的連接)。
使ExecuteQuery方法真正有用的是它允許你聲明以何種方式將sql表達式返回的值進行格式化。你可以通過如下兩種方式來實現:或者向方法中傳遞一個類型對象作爲參數,或者使用一個本方法的generic-based的版本。 例如,我們可以修改原來生成的GetProductsByCategory()的幫助方法-使用LINQ表達式--來替代ExecuteQuery方法來執行我們自己的原始的SQL表達式對數據庫進行操作並返回"Product"對象:
VB:
圖5
C#:
圖6
然後我們可以調用GetProductByCategory()幫助方法,代碼可以和前面的代碼完全相同:
圖7
但是和前面的不同的是,對數據庫進行操作的是我們自定義的SQL表達式--而不是linq表達式生成的動態sql語句。
爲更新自定義SQL表達式和對象跟蹤
默認情況下,當你用LINQ to SQL從數據模型對象中檢索數據時,它會跟蹤所有的變化並且當你對對象進行更新時更新這些變化。如果你調用DataContext中的"SbumitChanges()"方法,它將會啓動一個事務,並且將所有的變更更新至數據庫中。我本系列的第四部分Part 4中對這一點進行的較深刻地講解。
ExecuteQuery()的其中一個比較酷的我是,它完全參與跟蹤和更新模型中。比如,我們可以寫如下的代碼查詢屬於某一類別的產品並且將它們的價格打折10%:
圖8
因爲我們將ExecuteQuery()方法調用的GetProductByCategory()方法的結果集轉換爲"Product"的類型,LINQ to SQL知道跟蹤返回的Product對象。當我們調用Context對象中的"SubmitChanges()"方法時,它們將會被保存至數據庫中。
自定義類中的自定義SQL表達式
ExecuteQuery()方法允許你指定任何類來作爲SQL查詢的返回值類型。該類不是必須用LINQ to SQL ORM設計器生成的或者實現了某些自定義的接口-你可以將舊的類指定給它作爲它的返回值類型。 例如,我可以定義一個新的ProductSummary類,該類含有Product的屬性是Product類的屬性的一個子集,包括如下這些屬性(注意新的C#的自動屬性Automatic Properties特性):
圖9
然後我們可以在NorthwindDataContext中生成一個將該類作爲返回值類型的GetProductSummariesByCatetory()幫助方法。注意下面的SQL聲明是如何只請求Product中的我們需要的屬性的值的--ExecuteQuery()方法自動處理它返回的ProductSummary對象:
圖10
然後我們可以執行這個幫助方法並且用下面的代碼來對結果集進行遍歷:
圖11
用於插入、更新、刪除的自定義的SQL表達式
除了對查詢使用自定義的SQL表達式,我們也可以執行它們來進行插入、更新、刪除的邏輯。
我們可以通過如下方式實現這個目的:在DataContext的一個局部類中生成一個適當的插入、更新、刪除的局部方法。然後使用ExecuteCommand方法來寫我們需要執行的SQL語句。例如,爲了爲產品類覆蓋刪除的方法,我們可以定義如下的一個DeleteProduct局部方法:
圖12
然後如果我們寫如下的代碼從數據庫中移除一個特定的產品實例,LINQ to SQL將會調用DeleteProduct方法--該方法將會引起我們自定義的SQL語句替代自動生成的SQL語句:
圖13
總結
LINQ to SQL ORM自動生成並運行動態的SQL語句來對數據庫進行查詢、更新、插入和刪除。
在一些高級的場景中,或者在你想完全控制執行的SQL語句的情況下,你依然能夠自定義ORM來或者使用存儲過程,或者使用你自己定義的SQL表達式來替代原來它自動生成的SQL語句。這在創建和擴展你的數據層的時候給你提供了非常大的靈活性。
在接下來的本系列的帖子中,我將描述一些餘下的LINQ to SQL概念,包括:單表繼承,延遲/提前加載,優化併發衝突,處理多個場景。
希望這些對你有所幫助,
Scott