關於第四章中,SQL指令何時執行小方框的補充說明

來源:互聯網
上載者:User
  

關於第四章中,SQL 指令何時執行小方框的補充說明 文/黃忠成     在【極意之道- .NET Framework 3.5 資料庫開發聖典 ASP.NET】一書中,我於第四章,4-36頁處放上SQL指令何時執行的小方框,裡面的程式證明了當對同一LINQ To SQL回傳值下達多次LINQ  Expression運算式時,只有第一次會被轉成SQL指令後送往資料庫執行。 但這點與前面提及的Distinct、Count、Skip、Take的函式之用法形成了概念上的衝突,例如下面的Distinct函式用法。
var result = (from s1 in context.Order_Details              where s1.ProductID == 42 select s1.OrderID).Distinct().Count();
依據4-B01的程式結果看來,Distinct函式應該會先被執行,而Count函式會進入LINQ To Objects的範圍,但就事實而言,Distinct及Count函式都會被組合為單一SQL指令。
SELECT COUNT(*) AS [value]FROM (    SELECT DISTINCT [t0].[OrderID]    FROM [dbo].[Order Details] AS [t0]    WHERE [t0].[ProductID] = @p0    ) AS [t1]',N'@p0 int',@p0=42
那究竟是什麼,讓這兩個程式產生不同的結果呢?  事實上,這是因為4-B01的程式使用IEnumerable為函式間傳遞之型別所致,對於編譯器來說,並不會以物件的原始型別來推算呼叫的Extension Method,而是以最終型別,意思是,當你將LINQ To SQL的回傳值轉型為IEnumerable<T>後,那麼呼叫Where時,編譯器將決議成呼叫System.Linq.Enumerable中的Where函式,而非原本的IQueryable<T>中的Where函式。 所以,因為明白轉型成IEnumerable後,使得編譯器將後續的LINQ Expression全轉成了LINQ To Objects的呼叫了。 要正確完成累進式查詢的方式,是將程式4-B01中的IEnumerable<Customer>全換成IQueryable<Customer>。
static void NestedQuery(){      NorthwindDataContext context = new NorthwindDataContext ();      context.Log = Console.Out;      var fquery = GetFirstQuery(context);      var ret = DoSecondQuery(context, fquery);      foreach (var item in ret)         Console.WriteLine(item.CustomerID);} static IQueryable<Customer> GetFirstQuery(NorthwindDataContext context){      IQueryable<Customer> result = from s1 in context.Customers select s1;      return result;} static IQueryable<Customer> DoSecondQuery(NorthwindDataContext context,                                          IQueryable<Customer> firstQuery){       var result = from s1 in firstQuery                    where s1.CustomerID == "VINET"                      select s1;;        return result;}
 這個例子告訴我們一件很重要的事,如果你打算將LINQ的回傳值傳遞到另一個函式,或是回傳,要謹慎選擇型別,因為不同的型別,會影響後續使用LINQ時,編譯器如何決定呼叫的Extension Method,最後造成難以查覺的錯誤。 如果在撰寫LINQ/LINQ To SQL的通用函式時,不得已需要使用IEnumerable<T>(因為這是LINQ回傳值的通用基礎介面),也要加上依據實體介面來轉型的動作,如下例:
static void NestedQuery(){     DataClasses1DataContext context = new DataClasses1DataContext();     context.Log = Console.Out;     var fquery = GetFirstQuery(context);     var ret = DoSecondQuery(fquery);     foreach (var item in ret)        Console.WriteLine(item.CustomerID);} static IEnumerable<Customers> GetFirstQuery(DataClasses1DataContext context){      IEnumerable<Customers> result = from s1 in context.Customers select s1;      return result;}  static IEnumerable<Customers> DoSecondQuery(IEnumerable<Customers> firstQuery){              IEnumerable<Customers> result = null;       if (firstQuery is IQueryable<Customers>)           result = from s1 in (IQueryable<Customers>)firstQuery                     where s1.CustomerID == "VINET"                     select s1;        else           result = from s1 in firstQuery                    where s1.CustomerID == "VINET"                    select s1;;        return result;}
  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.