c# LINQ用法
一、什麼是LINQ
LINQ(讀音link)代表語言整合查詢(Language Integrated Query), 是.NEt框架的擴充套件,它允許我們用SQL查詢資料庫的方式來查詢資料的集合,使用它,你可以從資料庫、程式物件的集合以及XML文件中查詢資料
下面一個簡單的示例,可以查詢陣列中小於8的數字並輸出。
一般步驟:獲取資料來源、建立查詢、執行查詢。需要注意的是,儘管查詢在語句中定義,但直到最後的foreach語句請求其結果的時候才會執行
using System; using System.Collections.Generic; using System.Linq; namespace LINK查詢 { class Program { static void Main(string[] args) { int[] number = { 2, 4, 6, 8, 10 }; //獲取資料來源 IEnumerable<int> lowNum = from n in number//建立並存儲查詢,不會執行操作 where n < 8 select n; foreach(var val in lowNum)//執行查詢 { Console.Write("{0}", val); } Console.ReadKey(); } } }
二、查詢表示式的結構
查詢表示式由查詢體後的from子句組成,其子句必須按一定的順序出現,並且from子句和select子句這兩部分是必須的。先介紹一下子句
2.1 from子句
from子句指定了要作為資料來源使用的資料集合,它的語法是:
from Type Item in Items
其中Type是集合中元素的型別,是可選的,因為編譯器可以從集合來推斷型別。Item是迭代變數的名字。Items是要查詢的集合的名字,必須是可列舉型別的
它和foreach比較相似,但foreach語句在遇到程式碼時就執行其主體,二from子句什麼也不執行。它建立可以執行的後臺程式碼物件,只有在程式的控制流遇到訪問查詢變數的語句時才會執行
2.2 join子句
如果您對SQL中的join比較熟悉的話,那麼LINQ中的join對你來說也不是什麼難事,不熟悉的話,,當我沒說。
我們可以使用join來結合兩個或更多集合中的資料,它接受兩個集合然後建立一個臨時的物件集合
var query = from s in students join c in course on s.SID equals c.SID
equals用於比較相等性的欄位,不能使用“==”代替,下面示例中有三個學生和三門課程,我們要做的是查詢選修了歷史課的學生名
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace LINK查詢 { class Program { public class Student//宣告student類 { public int stId;//學生ID public string stuName;//學生姓名 } public class Course//宣告course類 { public int stId;//學生ID public string courseName;//課程名 } static Student[] students = new Student[] { new Student {stId = 1,stuName = "jack"}, new Student {stId = 2,stuName = "taylor"}, new Student {stId = 3,stuName = "fleming"} }; static Course[] courses = new Course[] { new Course{stId = 1,courseName = "art"}, new Course{stId = 2, courseName = "art"}, new Course{stId = 1,courseName = "history"}, new Course{stId = 3, courseName = "history"}, new Course{stId = 3,courseName = "physics"}, }; static void Main(string[] args) { //查詢所有選修了history課的學生名 var query = from s in students join c in courses on s.stId equals c.stId where c.courseName == "history" select s.stuName; foreach(string str in query) { Console.Write("{0}", str); } Console.ReadKey(); } } }
輸出 jack fleming
講解一下查詢過程:它會依次使用student中的物件與course中的所有物件進行對比,查詢是否符合s.stId equals c.stId where c.courseName == "history" 要求。
stID | stuName |
1 | jack |
2 | taylor |
3 | fleming |
stID | courseName |
1 | art |
2 | art |
1 | history |
3 | history |
3 | physics |
即先將(1,jack)和(1,art),(2,art)...(3,physics)分別匹配,然後再(2,taylor)和(1,art),(2,art)...(3,physics),直到所有都匹配完,最終可以找到兩條可以匹配的結果
2.3 let子句
let子句接受一個表示式的運算並且把它賦值給一個需要在其他運算中使用的識別符號,它是from...let...where片段中的一部分
var query = from a in groupA from b in groupB let sum = a + b where sum < 12 select new(a,b,sum);
2.4 where子句
where子句根據之後的運算來除去不符合要求的項,一個查詢表示式可以有任意多個where子句,一個項必須滿足所有的where條件才能避免被過濾,其語法為
where BoolenExpression1 where BoolenExpression2
前面的例子已經多次用過where,這裡就不舉例了
2.5 orderby子句
orderby可以很方便的將返回的資料進行排序,可選ascending和descending兩種方式,預設的是ascending
語法: orderby Expression ascending or descending 二選一
為join子句中的例子增加一個orderby子句,返回結果就變成了 fleming jack
var query = from s in students join c in courses on s.stId equals c.stId where c.courseName == "history" orderby s.stuName //排序 select s.stuName;
2.6 group子句
group子句可以讓你把select的結果按指定的鍵(key)進行分組,每一個分組由一個叫做鍵的欄位區分,分組本身是可列舉型別的並且可以列舉它的項
var query = from student in students group student by student.major; foreach (var s in query) { Console.WriteLine("{0}", s.key); foreach (var t in s) { console.writeLine("{0}", t.Name); } }
2.7 select子句
select子句指定所選定的物件哪部分應該被選擇。可以指定下面的任意一項
a: 整個資料項
b: 資料項的一個欄位
c: 資料項中幾個欄位組成的新物件(或類似其他值)
var query = from s in students select s;//整個資料項 var query = from s in students select s.stuName;//s中的一個欄位 var query = from a in groupA from b in groupB let sum = a + b where sum < 12 select new (a, b, sum);//a,b,sum組成的新欄位
2.8 查詢延續: into子句
查詢延續子句可以接受查詢的一部分結構並賦予一個名字,從而可以在查詢的另一部分中使用
var someInt = from a in groupA from b in groupB into groupAandB from c in groupAandB select c;
三、方法語法和查詢語法
在使用LINQ寫查詢時可以使用兩種形式的語法:查詢語法和方法語法
a:方法語法(method syntax) : 使用標準的方法呼叫,這些方法是一組叫做標準查詢運算子的方法
b:查詢語法(query method) : 看上去和SQL語句很相似,使用查詢表示式形式書寫。 微軟推薦使用查詢語法 ,因為它更易讀
在編譯時,CLR會將查詢語法轉換為方法語法
int[] num = { 2, 4, 6, 8, 10 }; var numQuery = from number in num//查詢語法 where number < 8 select number; var numMethod = num.Where(x => x < 8);//方法語法
它們得到的結果是一樣的。方法語法中where的引數使用了Lambda表示式