LINQ的作用


作為軟件開發人員,我們很大一部分時間都花在了獲取和操作數據上面。而說到數據,我們會自然而然地想到包含在關系數據庫里的信息、使用的XML文檔、保存在本地的DataSet、內存中的List列表等等。通常我們會對數據進行過濾和定位,查詢出符合要求的那一部分數據。

在.NET 3.5之前的版本中,與特定的數據類型打交道時,我們要使用特定特定命名空間下的特定類型。如下表列出了操作各種常見類型的API

目標數據

操作數據的.NET類型

關系數據

System.Data.dll和System.Data.SqlClient.dll

XML文檔數據

System.Xml.dll

元數據

System.Reflection命名空間

內存對象集合

System.Array和   System.Collection/System.Collection.Generic命名空間

雖然這些操作數據的方法本身沒有問題,比如我們都會直接使用ADO.NET、XML命名空間、反射服務以及各種集合類型。但是本質的問題在於,這些API的每一種本身只是一座孤島,提供了很少的集成方式。比如我們可以把ADO.NET DataSet保存為XML,然后通過System.Xml命名空間來操作。但是各API之間沒有替代品,我們沒法用ADO.NET API來操作XML,也不能用System.Array來操作關系數據。

LINQ(語言級集成查詢)的意圖就是提供一種統一且對稱的方式,讓程序員在廣義的數據上獲取和操作數據。通過使用LINQ,我們能夠在C#編程語言內直接創建被稱為“查詢表達式(query expression)”的實體。這些查詢表達式是基於許多查詢運算符(query operator)的,而且是有意設計成類似SQL表達式的。並且,查詢表達式可以用來與多種數據進行交互,以一種統一的方式來操作各種數據。

嚴格來說,LINQ是用來描述數據訪問總體方式的術語。LINQ to Object是針對實現了IEnumerable<T>的對象的LINQ;LINQ to SQL是針對關系數據庫的LINQ;LINQ to XML是針對XML文檔的LINQ。

LINQ除了提供一個統一的API來操作各種數據,並且為我們提供了編譯時類型檢查和動態創建查詢表達式的能力。

 

從這里開始

LINQ中最基本的數據單元是sequences和elements。一個sequence是實現了IEnumerable<T>的對象,而一個element是sequence中的每一個元素。如下,names就是一個sequence,”Tom”,“Dick”和”Harry”則是elements。

    string[] names = { "Tom", "Dick", "Harry" };

一個查詢運算符就是用來轉換sequence的方法。一個典型的查詢運算符接收一個輸入sequence並輸出一個轉換之后的sequence。在System.Linq.Enumerable類中,總共定義了40來個查詢運算符----全部用擴展方法來實現,他們被稱為標准查詢運算符。

一個查詢則是由查詢運算符來轉換sequence的一個表達式,最簡單的查詢由一個input sequence和一個查詢運算符組成。比如:

    string[] names = { "Tom", "Dick", "Harry"   };

    // 獲取所有長度大於等於4的名字
    IEnumerable<string> filteredNames = System.Linq.Enumerable.Where(
        names, n => n.Length >= 4);

    foreach (string n in filteredNames)
        Console.WriteLine(n);

輸出:
Dick
Harry

因為查詢運算符是以擴展方法實現的,所以我們可以直接在names對象上調用Where:

     // 獲取所有長度大於等於4的名字
     IEnumerable<string> filteredNames = names.Where(n => n.Length >= 4);

我們可以通過使用var關鍵字來進一步簡寫我們的query:

     var filteredNames = names.Where(n => n.Length >= 4);

注:在初學LINQ時,var關鍵字可能會影響可讀性,特別是在沒有IDE和智能提示的時候,因而如果可能,我會在本系列的開始盡量使用確切的返回類型。

大部分查詢運算符都接受一個lambda表達式作為參數,lambda表達式決定了查詢的行為特性和結果。在上例中,lambda表達式為:

          n => n.Length   >= 4  

Lambda表達式格式為:(parameters) => expression-or-statement-block

在這里的lambda表達式中,輸入參數n對應了names數組的每一個元素,其類型為string。Where運算符要求lambda表達式返回一個bool值,當結果為true時,表示該元素會包含在輸出sequence中。這里是Where運算符的方法簽名:

     public static IEnumerable<TSource> Where<TSource>
            (this IEnumerable<TSource> source, Func<TSource, bool> predicate)

下面的query獲取所有包含字母a的名字:

     string[] names = { "Tom", "Dick", "Harry" };
     IEnumerable<string> filteredNames = names.Where(n => n.Contains("a"));

     foreach (string name in filteredNames)
           Console.WriteLine(name);    // Harry

到現在為止,我們通過使用擴展方法和lambda表達式來建立了LINQ query。我們很快就能看到,這種策略非常的靈活和適合query的創建,因為我們可以級聯的使用查詢運算符。通常,這種方法被稱為LINQ方法語法(英文著作中稱為fluent systax)。C#還提供了另外一種書寫query的語法,叫做查詢表達式語法(英文著作中稱為query expression systax),下面是一個用查詢表達式語法建立的query,讓我們先睹為快:

      IEnumerable<string> filteredNames = from n in names
                                          where n.Contains("a")
                                          select n;    // Harry

方法語法和查詢表達式語法是互為補充的,在之后的LINQ方法語法和查詢語法一篇中,我們會詳解他們的聯系和區別。

 

 

   所有的linq對象,都繼承於IEnumerible、和IQuerible這兩個集合接口,所以在獲取集合時,可以轉換這兩種格式    IQuerible繼承自IEnumerible


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM