.NET中數(shù)據(jù)訪問方式(一):LINQ

語言集成查詢(Language-Integrated Query),簡稱LINQ,.NET中的LINQ體系如下圖所示:

LINQ Hierarchy

在編程語言層次,LINQ對于不同的數(shù)據(jù)源提供了相同的查詢語法,方便了程序員操作不同的數(shù)據(jù)源。

可查詢類型

LINQ之所以能夠使用相同的語法操作不同的數(shù)據(jù)源,是因為和LINQ直接打交道的是可查詢類型而非數(shù)據(jù)源,在LINQ中,直接或間接實現(xiàn)了IEnumerable<T>接口的類型稱為可查詢類型, .NET中如:List<T>,Dictionary<TKey,TValue>,數(shù)組(由CLR負責隱式實現(xiàn)IEnumerable<T>接口)等,實現(xiàn)了IEnumerable<T>接口。
IQueryable<out T>繼承自IEnumerable<T>,是個標記接口。

可查詢類型無需額外操作即可進行LINQ操作,若數(shù)據(jù)源在內(nèi)存中不以可查詢類型的形式存在,那么LINQ提供程序必須要先將數(shù)據(jù)源轉(zhuǎn)換為可查詢類型,如LINQ to XML將XML文件轉(zhuǎn)換為可查詢的XElement類型:
XElement contacts = XElement.Load(@"c:\myContactList.xml");

LINQ 提供程序

LINQ提供程序(LINQ Provider)提供了對特定的數(shù)據(jù)源進行標準的LINQ操作及一些擴展操作(如:LINQ to XML),不同的LINQ提供程序?qū)τ谝恍┫嗤Q的擴展方法會提供不同的實現(xiàn)方式。.NET中預定義的LINQ提供程序包括:LINQ to Object、LINQ to XML (C#)LINQ to SQL、LINQ to DataSet、LINQ to Entities
LINQ to SQL不建議使用,用LINQ to Entities來替代。

LINQ查詢包含三個步驟:

  1. 獲取數(shù)據(jù)源
  2. 創(chuàng)建查詢語句
  3. 執(zhí)行查詢

LINQ查詢方式

  • LINQ 表達式(又稱為查詢表達式
    from關(guān)鍵字開頭,select關(guān)鍵字結(jié)尾。

  • 擴展方法(又稱為標準查詢
    System.Linq.Enumerable類和System.Linq.Queryable類,分別針對IEnumerable<T>IQueryable<T>接口進行的擴展。.NET也提供了幾個對IEnumerableIQueryable接口進行操作的擴展方法,如: Cast<TResult>OfType<TResult>。

  • LINQ 表達式和擴展方法混合使用

(from e in Employees
where e.Salary>8000
select e).ToList()

LINQ表達式和擴展方法對比:

  • 對于排序、分組、聯(lián)合查詢使用LINQ表達式更為方便
//以排序為例,使用年齡、姓名、郵箱進行排序,
//LINQ表達式中使用逗號分隔排序字段,而擴展方法則需要多次調(diào)用相應的擴展方法
var result= from e in Employees
            where e.Age>50 && e.Salary>8000
            orderby e.Age,e.Name,e.Email
            select e;

//等價的擴展方法
var result=Employees
           .Where(e=>e.Age>50 && e.Salary>8000)
           .OrderBy(e=>e.Age)
           .ThenBy(e=>e.Name)
           .ThenBy(e=>e.Email);
  • 擴展方法能夠提供比LINQ表達式更復雜的查詢
//取第26行到36行范圍內(nèi)的數(shù)據(jù)
var result=Employees.Skip(25).Take(10);

//使用LINQ表達式我表示寫不出來......

LINQ表達式是對常用擴展方法在語法層面上的簡化,LINQ表達式有著更好的可讀性,在編譯時LINQ表達式會被轉(zhuǎn)化為對擴展方法的調(diào)用。

LINQ查詢特點:

  • 延遲查詢
    若查詢表達式的返回結(jié)果是IEnumerable<T>類型,則在聲明查詢表達式時不會執(zhí)行查詢,而是在迭代查詢變量時才進行查詢。

    MSDN上的經(jīng)典LINQ查詢流程圖(延遲查詢)

  • 立即查詢
    若查詢表達式返回單個值或者使用了ToList<T>、ToArray<T>等方法時會執(zhí)行立即查詢,因為這些操作會遍歷數(shù)據(jù)。

一句話總結(jié),若查詢表達式不包含對數(shù)據(jù)源的遍歷操作則執(zhí)行延遲查詢,否則會進行立即查詢。

LINQ表達式中的查詢關(guān)鍵字

表格中的英文沒什么難點,就不翻譯了 :)

關(guān)鍵字 描述
from Specifies a data source and a range variable (similar to an iteration variable).
where Filters source elements based on one or more Boolean expressions separated by logical AND and OR operators.
select Specifies the type and shape that the elements in the returned sequence will have when the query is executed.
group Groups query results according to a specified key value.
into Provides an identifier that can serve as a reference to the results of a join, group or select clause.
orderby Sorts query results in ascending or descending order based on the default comparer for the element type.
join Joins two data sources based on an equality comparison between two specified matching criteria.
let Introduces a range variable to store sub-expression results in a query expression.
in Contextual keyword in a join clause.
on Contextual keyword in a join clause.
equals Contextual keyword in a join clause.
by Contextual keyword in a group clause.
ascending Contextual keyword in an orderby clause.
descending Contextual keyword in an orderby clause.

兩個接口

在LINQ中,一個查詢表達式被編譯為表達式樹或者委托,查詢結(jié)果為IEnumerable<T>類型則被編譯為委托,查詢結(jié)果是IQueryableIQueryable<T>類型則被編譯為表達式樹,在運行時表達式樹會被解析為適合于數(shù)據(jù)源的查詢語句。

  • System.Collection.Generic.IEnumerable<T>
    IEnumerable先將數(shù)據(jù)放到本地內(nèi)存中,然后再執(zhí)行過濾操作(如果有的話),適合于對當前進程中的數(shù)據(jù)進行查詢操作,如:LINQ to XMLLINQ to Object
  • System.Linq.IQueryable<T>
    在執(zhí)行查詢操作時,IQueryable先在服務器端進行過濾操作(如果有的話),然后再將數(shù)據(jù)放到本地內(nèi)存中。
    IQueryable適合使用對進程外(如數(shù)據(jù)庫)的數(shù)據(jù)進行查詢操作,如:LINQ to Entities。

兩個命名空間

System.Linq

System.Linq命名空間中包含用于LINQ查詢的類和接口

System.Linq.Expressions

System.Linq.Expressions 命名空間包含了用于創(chuàng)建表達式樹的類、 接口。

LINQ的優(yōu)缺點

優(yōu)點

  1. 對不同的數(shù)據(jù)源提供了幾乎一致的查詢操作,這可使我們更多的去關(guān)注業(yè)務邏輯而非對數(shù)據(jù)源的操作
  2. 提供編譯期的類型檢查
  3. 在書寫LINQ查詢表達式時可以使用Visual Studio的智能提示
  4. 調(diào)試方便

缺點

  1. 對于復雜的查詢操作顯得力不從心
  2. 容易寫出性能不高的查詢表達式

結(jié)語

本篇是自己學習LINQ的總結(jié),不求面面俱到。通篇以文字敘述為主,輔以少量代碼,若有錯誤希望大家指出。

工具推薦

LINQ Pad是一款輕量級的數(shù)據(jù)查詢工具,在LINQ Pad中可以使用LINQ表達式、擴展方法、SQL語句等對數(shù)據(jù)庫進行操作,簡單易用功能強大。

LINQ Pad

書目推薦:

《LINQ Interview Questions Answers》

參考文章

Introduction to LINQ Queries (C#)
Standard Query Operators Overview (C#)
Query Expression Syntax for Standard Query Operators (C#)
Data Transformations with LINQ (C#)
LINQ provider basics
Enabling a Data Source for LINQ Querying
LINQ: Building an IQueryable Provider – Part I

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容