LINQ 進階 總結
查詢執行的時機:
查詢分爲以下三步:獲取數據源、定義查詢、執行查詢;
定義查詢後,查詢直到需要枚舉結果時才被真正執行,這種方式稱爲 “ 延遲執行 (deferred execution)” ;當查詢方法返回單一值時,查詢立即執行;
LINQ 查詢的兩種方式:
1 、 Method Syntax, 查詢方法方式:主要利用System.Linq.Enumerable 類中定義的擴展方法和 Lambda 表達式方式進行查詢
2 、 Query Syntax, 查詢語句方式:一種更接近 SQL 語法的查詢方式;可讀性更好
查詢語句和查詢方法:
查詢語句與查詢方法存在着緊密的關係: CLR 本身並不理解查詢語句,它只理解查詢方法,編譯器負責在編譯時將查詢語句翻譯爲查詢方法,大部分查詢方法都有對應的查詢語句形式:如 Select() 對應 select 、 OrderBy() 對應 orderby ,部分查詢方法目前在 C# 中還沒有對應的查詢語句:如 Count() 和 Max() 這時只能採用以下替代方案:
1 、查詢方法;
2 、查詢語句 + 查詢方法的混合方式;
一般情況下,建議使用可讀性更好的查詢語句。
高級查詢方法:
聚合類
Count( 返回集合項的數目 ) :
(1) 、混合模式 : int count = (from p in foxRiver8 where p.Age <= 30 select p).Count();
(2) 、純粹查詢方法模式 : int count = foxRiver8
.Where(p => p.Age <= 30).Count();
Max( 返回集合中的最大值 ):
(1) 、混合模式: int maxAge = (from p in foxRiver8
select p.Age).Max();
(2) 、純粹查詢方法模式: int maxAge = foxRiver8
.Select(p => p.Age).Max();
Min( 返回集合中的最小值 ):
(1) 、混合模式: int maxAge = (from p in foxRiver8
select p.Age).Min();
(2) 、純粹查詢方法模式: int maxAge = foxRiver8
.Select(p => p.Age).Min();
Average( 返回集合的平均值 ):
(1) 、混合模式: double averageAge = (from p in foxRiver8 select p.Age).Average();
(2) 、純粹查詢方法模式: double averageAge = foxRiver8.Select(p => p.Age) .Average();
Sum( 返回集合的總和 ):
(1) 、混合模式: Int sumAge = (from p in foxRiver8
select p.Age).Sum();
(2) 、純粹查詢方法模式: int sumAge = foxRiver8
.Select(p => p.Age) .Sum();
排序類 :
ThenBy( 提供複合排序條件 ):
(1) 、查詢方法 : var q = foxRiver8.OrderBy(p => p.FirstName).ThenBy(p=>p.LasName).ThenBy(p=> p.Age);
(2) 、查詢語句 : var q = from p in foxRiver8 orderby p.FirstName, p.LasName, p.Age select p;
分區類 :
Take( 提取指定數量的項 )/Skip( 跳過指定數量的項並獲取剩餘的項 ) :
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var q = numbers.Skip(1).Take(3);
foreach (var item in q)
{ Console.WriteLine(item); }
說明:跳過前 1 條記錄,連續提取 3 條記錄,得到 2 3 4
TakeWhile/SkipWhile( 根據指定條件提取項 / 根據指定條件跳過項 )
int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var q = numbers.SkipWhile(i=>i % 3 != 0).TakeWhile(i =>i%2!= 0);
foreach (var item in q){Console.WriteLine(item);}
集合類 :
Distinct( 去掉集合中的重複項 ):
int[] factorsOf300 = { 2, 2, 3, 5, 5 };
var uniqueFactors = factorsOf300.Distinct();
輸出 : 2 3 5
生成類
Range( 生成一個整數序列 ):
var numbers =Enumerable.Range(1, 10);
foreach (var item in numbers)
{ Console.WriteLine(item); }
Repeat( 生成一個重複項的序列 ):
var numbers =Enumerable.Repeat(“Beijing 2008”, 10);
foreach (var item in numbers)
{ Console.WriteLine(item); }
注:和其他幾類方法不同, Range/Repeat 不是擴展方法,而是普通的靜態方法; Range 只能產生整數序列; Repeat 可以產生泛型序列;所有的查詢方法都存放在 System.Linq.Enumerable 靜態類中。