Entity Framework 4 in Action讀書筆記——第四章:使用LINQ to Entities查詢:執行手動查詢

來源:互聯網
上載者:User
文章目錄
  • 4.8.1 帶參數的查詢
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)問題,它幾乎獨立與你寫的任何查詢。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.