LINQ使用(一)

一、什麼是LINQ

LINQ即 Language Integrated Query,語言集成查詢,是微軟新增的一種類似SQL查詢數據庫的方式的自然查詢方法,是.net框架的擴展,查詢時數據集時,非常方便,不用使用for/foreach循環遍歷了

大約有40多個關鍵字幫助查詢。
Where、Select、SelectMany、Skip、SkipWhile、Take、TakeWhile、Join、GroupJoin、Concate、OrderBy、OrderByDescending、ThenBy、ThenByDescending、Reverse、GroupBy、Distinct、Union、Intersect、Except、AsEnumerable、AsQueryable、ToArray、ToList、ToDictionary、ToLookup、OfType、Cast、SequenceEqual、First、FirstOrDefault、Last、LastOrDefault、Single、SingleOrDefault、ElementAt、ElementAtOrDefault、DefaultIfEmpty、All、Any、Contains、Count、LongCount、Sum、Min、Max、Average、Aggregate、equals/Equals、from/From、in/In、into/Into、key、let、Group、Range、Repeat。

二、如何使用LINQ

有兩種方式,第一種,可以像SQL語句一樣查詢,也可以使用方法調用的方式查詢。

 // LINQ Query
 //Method 1:
 var bmws = from Car in MyCars
            where Car.Make == "BMW"
            select Car;
//Method 2:
var bmws2 = MyCars.Where(p => p.Make == "BMW" && p.Year == 2018);

第二種p=>p.Make使用了lamda表達式,使語句更加簡潔。

舉個栗子:

  1. 定義1個Car類 class Car;
  2. 創建1個Car類的集合 List MyCars = new List();
  3. 通過LINQ進行查詢、排序、判斷、和輸出。

以下是一些例子,可模仿一下。

class Program
 {
     class Car
     {
         public string Make;
         public int Year;
     }
     
     static void Main(string[] args)
     {
         List<Car> MyCars = new List<Car>();
         MyCars.Add(new Car() { Make = "BMW", Year = 2018 });
         MyCars.Add(new Car() { Make = "ZhongHua", Year = 2019 });
         MyCars.Add(new Car() { Make = "BMW", Year = 2019 });
         MyCars.Add(new Car() { Make = "BYD", Year = 2018 });
         MyCars.Add(new Car() { Make = "HongQi", Year = 2017 });

         // LINQ Query
         var bmws = from Car in MyCars
                    where Car.Make == "BMW"
                    select Car;

         var bmws2 = MyCars.Where(p => p.Make == "BMW" && p.Year == 2018);

         //SORT
         var orderedCars = from Car in MyCars
                           orderby Car.Year descending
                           select Car;

         var orderedCars2 = MyCars.OrderByDescending(p => p.Year);

         //choose first pick
         var firstCar = MyCars.First(p => p.Make == "BMW");
         //Order then choose the first
         var firstBMW = MyCars.OrderByDescending(p => p.Year).First(p => p.Make == "BMW");

         //print
         Console.WriteLine(MyCars.TrueForAll(p => p.Year > 2012));     //True

         MyCars.ForEach(p => Console.WriteLine("{0}{1:c}", p.Make, p.Year));  // BMW ¥2018.00...

         Console.WriteLine(MyCars.Exists(p => p.Make == "DaZhong"));  //false

         Console.WriteLine(MyCars.GetType());  // System.Collections.Generic.List`1[LINQ_Test.Program+Car]

         //caculate
         MyCars.ForEach(p => p.Year += 1);

         var newCars = from Car in MyCars
                       where Car.Make == "BMW"
                       && Car.Year == 2018
                       select new { Car.Make, Car.Year };
     }

 }

三、個人使用愛好

  1. Where中判斷語句傳入函數

LINQ中Where語句,可以看出來,裏面其實是一個bool類型的判斷,返回true or false。

所以,使用時不必拘泥與對數據集成員本身的判斷,騷操作寫入一個返回值爲bool類型的函數,函數其中1個參數爲數據集成員,如下所示,CheckHiddenPoint§函數就是對數據集對象進行處理,但是返回值爲bool類型的,如此就可以避免採用for循環進行遍歷了。

var checkEnts = listHiddenEntEx.AsParallel().Where(p =>CheckHiddenPoint(p)).ToList();
  1. 可以看到,linq支持並行處理,即多個成員同時進行判斷處理,添加關鍵字.AsParallel.
//串行處理,1個接1個
var checkEnts = listHiddenEntEx.Where(p =>CheckHiddenPoint(p)).ToList();
//並行處理,加快處理速度。
var checkEnts = listHiddenEntEx.AsParallel().Where(p =>CheckHiddenPoint(p)).ToList();
  1. 使用並行計算時,如果要向同一個List集合中添加數據時,會造成兩條數據同時向List中同一位置寫入數據,會有資源爭搶問題,會報訪問index錯誤,並且並行過程中不可對寫入的數據集進行Clear()操作,也會發生訪問Index錯誤。未防止錯誤發生,可去掉並行處理。

一般不建議寫入數據集過程中還要清理數據集的操作,會引發混亂。

如果單純想並行寫入同一個數據集,可採用lock的方法鎖定數據集,每次只允許1個數據集寫入數據。即可保證訪問Index的正確性。

特別強調並行計算可以節約時間,但是加鎖會減緩時間,讓衆多線程等待1個線程完成操作之後才能處理,所以到底是節約了時間沒有,值得思考。

dic.AsParallel.Alll(p=>{AddRecord(p.Key,p.Value); return true;})
//聲明公共數據集
List<string>() errorRecords = new List<string>();

public bool AddRecord(string A, string B){
	//幹活
	lock (errorRecords)
	{
	 errorRecords.Add("發生錯誤"});
	}
}
  1. 兩個數據集進行判斷,採用SQL語句寫。listWWTPEnt 與 listInAreaEnt 爲2個List數據集,寫2次from,即可以對兩個數據集成員同時判斷。

    該方法等效於for循環2次

  var listWSandPFK = from wwtp in listWWTPEnt
                     from inarea in listInAreaEnt
                     where isPfkInPsInArea(inarea, wwtp)
                     select new { inarea, wwtp };
  foreach (var item in listWSandPFK)
  {
	//幹活
  }
//等效於for循環2次
  for (int i = 0; i < listInAreaEnt.Count; i++)
  {
      for (int j = 0; j < listPKEnt.Count; j++)
      {
          if (isPfkInPsInArea(listInAreaEnt[i], listPKEnt[j]))
          {
              //幹活
          }
      }
  }
  1. 分組處理。有時候1個數據集需要根據成員屬性進行分組,使用GroupBy關鍵字。
List<CommDB.CCommStruct.CheckCondition> listCheckCondition;
//幹活

//按 應用圖層和幾何類型分組
   var checkGroups = listCheckCondition.GroupBy(p => new { p.yycm, p.jhlx }).ToList();  
    for (int i = 0; i < checkGroups.Count; i++)   //group.Key 爲應用圖層名
    {
    	string layer = checkGroups[i].Key.yycm;
    	string geoType = checkGroups[i].Key.jhlx
	List<CommDB.CCommStruct.CheckCondition> newGroupi = checkGroups[i];
	//幹活
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章