Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:执行手动查询...
4.8 執行手動查詢
有很多原因決定你會手動寫查詢。或許由EF生成的SQL太慢,又或許執行起來浪費了太多資源。另一種情況可能是當你動態生成一個如此復雜的查詢,創建SQL代碼比使用LINQ to Entities簡單。
在這種情況下,你自己可以使用ObjectContext類的ExecuteStoreQuery<T>創建一個SQL命令。它允許你發出任意的查詢并將查詢結果映射到類。它的使用如下:
var details = ctx.ExecuteStoreQuery<OrderDetail>("Select * from OrderDetail");就是這么簡單。查詢被執行,列自動映射到實體。關于映射階段有一個小小的提示:它繞過了EDM,而是使用另外一種基于屬性-列名匹配的機制。這一行為如圖:
這個映射解決方案的有一定的局限性:
1.如果一個屬性跟相應的列名稱不同,映射就不會執行并拋出異常。你可以很容易的通過在查詢中使用AS SQL子句重命名列解決這個問題。
2.不能映射到有復雜屬性的實體,因為沒有辦法將復雜屬性內的名稱和列進行匹配。
當然,你可以映射返回的數據到任何類型的類,不僅僅是那些定義在EDM中的。假設,你創建了一個類OrderDetailProjection,有Quantity,UnitPrice和Discount屬性。你可以寫一個查詢,從OrderDetail表中取出Quantity, UnitPrice和 Discount列,并將結果映射到OrderDetailProjection。
public class OrderDetailProjection {public int Quantity { get; set; }public decimal UnitPrice { get; set; }public decimal Discount { get; set; } } var details = ctx.ExecuteStoreQuery<OrderDetailProjection>("Select quantity, unitprice, discount from OrderDetail");注意:
通過ExecuteStoreQuery<T>,你也可以啟動存儲過程。但是我們不建議這樣做,因為EF本身就支持存儲過程并且提供了比ExecuteStoreQuery<T>更多的選項。
如果查詢帶有參數,你可以使用ExecuteStoreQuery<T>的重載方法,它接受參數列表。這可能會非常棘手,所以讓我們看一看。
4.8.1 帶參數的查詢
當初EF團隊設計如何傳遞參數時,有很多的選擇。通過選擇,現在有兩種操作參數的方式。
1.使用帶有編號列表,跟String.Format方法一樣。
2.使用ADO.NET語法
下面,我們詳細看一下這兩種方式。
使用帶編號的列表
這是最簡單的辦法。在SQL查詢中,將數字放在花括號中代表參數。然后,你在方法的第二個參數中傳遞參數。參數既可以是簡單的數值也可以是DbParameter類的實例。這里有一些建議,要牢記:
1.如果你使用DbParameter實例,你必須使用與數據庫Provider相應的具體類型。例如,如果對SQL Server就必須使用SqlParameter,對OLE DB就必須使用OleDbParameter。如果你使用其他的實例,在運行時會得到InvalidCastException。
2.如果你有多個參數,你不能混用DbParameter實例和純值。你必須選擇其一。否則,在運行時會得到InvalidOperationException。
3.如果你使用簡單的數值作為參數,它們傳過來的順序必須和它們在查詢中的順序一樣。
使用簡單數值傳遞參數
var names = ctx.ExecuteStoreQuery<string>("SELECT name FROM company WHERE shippingcity = {0} and billingcity = {1}", "New York", "Seattle");使用SqlParameter傳遞參數
var p0 = new SqlParameter("p0", DbType.String) { Value = "New York" }; var p1 = new SqlParameter("p1", DbType.String) { Value = "Seattle" }; var names = ctx.ExecuteStoreQuery<string>("SELECT name FROM company WHERE shippingcity = {0} and billingcity = {1}", p0, p1);正如你所見,這里沒有什么特別困難的。只要注意我們前面提到的陷阱即可。
注意:
即使此語法可能會導致你認為可以通過SQL注入攻擊的影響,但絕對不是這種情況。參數往往作為安全的方式傳遞給數據庫。
現在,讓我們繼續談談使用傳統的參數
使用傳統的參數
通過經典的ADO.NET寫查詢時,你通常寫這樣的東西表達參數:
SELECT * FROM table WHERE id = @id這種語法對SQL Server provider是有效的。如果你使用OLE DB provider,你必須問號(?)代替@paramname。
這種方法使用ExecuteStoreQuery<T>方法仍然完全有效。不是將數字放在花括號中,而是放置參數。其他都一樣。參數的值仍然可以作為簡單數值或參數傳遞過來。
使用簡單數值傳遞參數
var names = ctx.ExecuteStoreQuery<string>("SELECT name FROM company WHERE shippingcity = @p0 and billingcity = @p1","New York", "Seattle");使用SqlParameter傳遞參數
var p0 = new SqlParameter("p0", DbType.String) { Value = "New York" }; var p1 = new SqlParameter("p1", DbType.String) { Value = "Seattle" }; var names = ctx.ExecuteStoreQuery<string> ("SELECT name FROM company WHERE shippingcity = @p0 and billingcity = @p1", p0, p1); 如果將這段代碼和前面的代碼比較,你會發現只是SQL代碼中參數聲明發生了改變。剩下的仍然是相同的,也就是說,沒有更多的東西需要學習。到目前為止,我們已經介紹了如何編寫功能強大的查詢。現在,我們換個角度思考:你有多少相關的實體需要查詢?是直接檢索出所有相關的實體,還是根據代碼需要。這顯然是一個獲取(fetching)問題,它幾乎獨立與你寫的任何查詢。
轉載于:https://www.cnblogs.com/nianming/archive/2011/09/16/2179238.html
總結
以上是生活随笔為你收集整理的Entity Framework 4 in Action读书笔记——第四章:使用LINQ to Entities查询:执行手动查询...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: windows xp 下使用 windo
- 下一篇: 经典排序算法-MFC实现之2:问题