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