C# LINQ學習筆記一:走進LINQ的世界

来源:https://www.cnblogs.com/atomy/archive/2019/12/25/12084521.html
-Advertisement-
Play Games

本筆記摘抄自:https://www.cnblogs.com/liqingwen/p/5832322.html,記錄一下學習過程以備後續查用。 LINQ 簡介: 語言集成查詢(LINQ)是Visual Studio 2008和.NET Framework 3.5版中引入的一項創新功能。 傳統上,針對 ...


    本筆記摘抄自:https://www.cnblogs.com/liqingwen/p/5832322.html,記錄一下學習過程以備後續查用。

    LINQ 簡介:

    語言集成查詢(LINQ)是Visual Studio 2008和.NET Framework 3.5版中引入的一項創新功能。

 傳統上,針對數據的查詢都是以簡單的字元串表示,而沒有編譯時類型檢查或IntelliSense支持。此外,您還必須針對以下各種數據源學習一種不同的查詢

語言:SQL資料庫、XML文檔、各種Web服務等。通過LINQ,可以使用語言關鍵字和熟悉的運算符針對強類型化對象集合編寫查詢。

    在Visual Studio中,可以為以下數據源編寫LINQ查詢:SQL Server資料庫、XML文檔、ADO.NET數據集以及支持 IEnumerable或泛型 IEnumerable<T> 

介面的任意對象集合,使用要求:項目 ≥ .NET Framework 3.5。

    一、LINQ查詢

    查詢是一種從數據源檢索數據的表達式。隨著時間的推移,人們已經為各種數據源開發了不同的語言。例如,用於關係資料庫的SQL和用於XML的XQuery。

因此,開發人員不得不針對他們必須支持的每種數據源或數據格式而學習新的查詢語言。LINQ通過提供一種跨數據源和數據格式使用數據的一致模型,簡化

了這一情況。在LINQ查詢中,始終會用到對象。可以使用相同的編碼模式來查詢和轉換XML文檔、SQL資料庫、ADO.NET數據集、.NET集合中的數據以及

對其有LINQ提供程式可用的任何其他格式的數據。

    1.1 查詢操作的三個部分

    操作三部曲:①取數據源 ②創建查詢 ③執行查詢

    下麵代碼演示LINQ to OBJECT:

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ to OBJECT
            //查詢三部曲:1、獲取數據源
            var nums = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

            //查詢三部曲:2、創建查詢
            var query =
                from num in nums
                where (num % 2) == 0
                select num;

            //查詢三部曲:3、執行查詢
            foreach (var num in query)
            {
                Console.Write($"{num} ");
            }

            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    下圖顯示了完整的查詢操作。在LINQ中,查詢的執行與查詢本身截然不同。換句話說,查詢本身指的是只創建查詢變數,不檢索任何數據。

    1.2 數據源

    在上一個示例中(LINQ to OBJECT),由於數據源是數組,因此它隱式支持泛型 IEnumerable<T> (可枚舉)介面。支持 IEnumerable<T> 或派生介面(如

泛型IQueryable<T>)的類型稱為可查詢類型。

    可查詢類型不需要進行修改或特殊處理就可以用作LINQ數據源。如果源數據還沒有作為可查詢類型出現在記憶體中,則LINQ提供程式必須以此方式表示源數

據。例如,LINQ to XML將XML文檔載入到可查詢的 XElement 類型中。

    下麵代碼演示LINQ to XML:

    創建一個Test.xml文件,放在主目錄下。

<DocumentElement>
  <Category>
    <MO_NO>MOA1911070001</MO_NO>
    <MRP_NO>8198712090963008</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110701</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070002</MO_NO>
    <MRP_NO>8193000000003172</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110702</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070003</MO_NO>
    <MRP_NO>8193002043133003</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110702</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070004</MO_NO>
    <MRP_NO>8193002043133004</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110702</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070005</MO_NO>
    <MRP_NO>8193002043133005</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110702</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070006</MO_NO>
    <MRP_NO>8198922092971001</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110703</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070007</MO_NO>
    <MRP_NO>8198922092971002</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110703</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070008</MO_NO>
    <MRP_NO>8198922092971010</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110703</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070009</MO_NO>
    <MRP_NO>8198922092971200</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110703</BIL_NO>
  </Category>
  <Category>
    <MO_NO>MOA1911070010</MO_NO>
    <MRP_NO>8199862094443008</MRP_NO>
    <QTY>1.00000000</QTY>
    <BIL_NO>MPA19110704</BIL_NO>
  </Category>
</DocumentElement>
View Code
    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ to XML
            var xe = XElement.Load(@"..\..\Test.xml");
            var query =
                from item in xe.Descendants("Category")
                select item;
            foreach (var item in query)
            {
                Console.WriteLine($"MO_NO={item.Element("MO_NO").Value}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    在LINQ to SQL中,首先需要生成對象模型映射到關係資料庫,然後針對這些對象編寫查詢,由LINQ to SQL在運行時處理與資料庫的通信。

    準備一:下文中用到的Northwind資料庫,下載地址為:https://www.microsoft.com/en-us/download/confirmation.aspx?id=23654

    準備二:若本機沒有安裝LINQ to SQL工具,可參考安裝教程:https://blog.csdn.net/u011176794/article/details/90287293

    準備三:添加新建項,選擇LINQ to SQL類,命名為Sample。

    準備四:伺服器資源管理器的數據連接中,右鍵添加連接,依導向連接至SQL Server資料庫。

    準備五:將相關數據表拖至Sample.dbml中並保存。

    準備六:添加引用System.Data.Linq。

    下麵代碼演示LINQ to SQL:

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ to SQL
            var db = new SampleDataContext();
            var query =
                from cust in db.Customers
                where cust.City == "London"
                select cust;
            foreach (var item in query)
            {
                Console.WriteLine($"CustomerID={item.CustomerID}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    1.3查詢

    查詢指定要從數據源中檢索的信息,可以指定在返回這些信息之前如何對其進行排序、分組和結構化。 查詢存儲在查詢變數中,並用查詢表達式進行初始

化。之前的示例中的查詢是從整數數組中返回所有的偶數。該查詢表達式包含三個子句:fromwhereselect。如果您熟悉SQL,您會註意到這些子句的

順序與SQL中的順序相反,from 子句指定數據源,where 子句指定應用篩選器,select 子句指定返回的元素的類型。目前需要註意的是,在LINQ中,查詢

變數本身不執行任何操作並且不返回任何數據,它只是存儲在以後某個時刻執行查詢時為生成結果而必需的信息。

    1.4 查詢執行

    1.延遲執行

    如前所述,查詢變數本身只是存儲查詢命令,實際的查詢執行會延遲到在foreach語句中迴圈訪問查詢變數時發生,此概念稱為“延遲執行”。

    2.強制立即執行

    對一系列源元素執行聚合函數的查詢必須首先迴圈訪問這些元素,CountMaxAverageFirst就屬於此類查詢。由於查詢本身必須使用foreach以便

返回結果,因此這些查詢在執行時不使用顯式foreach語句。另外還要註意,這些類型的查詢返回單個值,而不是IEnumerable集合。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ查詢強制立即執行一
            var nums = new int[7] { 0, 1, 2, 3, 4, 5, 6 };
            var query =
                from num in nums
                where (num % 2) == 0
                select num;
            var numCount = query.Count();
            Console.WriteLine($"NumCount={numCount}");
            Console.Read();
            #endregion
        }
    }
View Code     運行結果如下:

    若要強制立即執行任意查詢並緩存其結果,可以調用ToList<TSource>ToArray<TSource>方法。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ查詢強制立即執行二
            var nums = new int[7] { 0, 1, 2, 3, 4, 5, 6 };

            var query2 =
               (from num in nums
                where (num % 2) == 0
                select num).ToList();

            var query3 =
                (from num in nums
                 where (num % 2) == 0
                 select num).ToArray();

            Console.WriteLine($"NumCount={query2.Count}");
            Console.WriteLine($"NumCount={query3.Length}");
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    二、基本 LINQ 查詢操作

    2.1 獲取數據源:from

    在LINQ查詢中,第一步是指定數據源。像在大多數編程語言中一樣,必須先聲明變數,才能使用它。在LINQ查詢中,最先使用from子句的目的是引入數據

源和範圍變數。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ to SQL
            var db = new SampleDataContext();

            //query是IEnumerable<Cutsomer>類型
            //數據源(db.customers)和範圍變數(cust)
            var query =
                from cust in db.Customers
                where cust.City == "London"
                select cust;

            foreach (var item in query)
            {
                Console.WriteLine($"CustomerID={item.CustomerID}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    範圍變數類似於foreach迴圈中的迭代變數,但在查詢表達式中,實際上不發生迭代。執行查詢時,範圍變數將用作對customers中的每個後續元素的引用。

因為編譯器可以推斷cust的類型,所以您不必顯式指定此類型。

    2.2 篩選:where

    也許最常用的查詢操作是應用布爾表達式形式的篩選器,此篩選器使查詢只返回那些表達式結果為true的元素。使用where子句生成結果,實際上,篩選器

指定從源序列中排除哪些元素。

    您可以使用熟悉的C#邏輯AND(&&)OR(||)運算符來根據需要在where子句中應用任意數量的篩選表達式。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 篩選:where
            var db = new SampleDataContext();

            var query1 =
                from cust in db.Customers
                where cust.City == "London" && cust.CustomerID == "AROUT"
                select cust;
            var query2 =
                from cust in db.Customers
                where cust.City == "London" || cust.City == "Paris"
                select cust;

            foreach (var item in query1)
            {
                Console.WriteLine($"query1->City={item.City},CustomerID={item.CustomerID}");
            }
            foreach (var item in query2)
            {
                Console.WriteLine($"query2->City={item.City},CustomerID={item.CustomerID}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    2.3 排序:orderby

    通常可以很方便地將返回的數據進行排序。orderby子句將使返回的序列中的元素按照被排序的類型的預設比較器進行排序。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 排序:orderby
            var db = new SampleDataContext();
            var query =
                from cust in db.Customers
                where cust.City == "London"
                orderby cust.CustomerID
                select cust;
            foreach (var item in query)
            {
                Console.WriteLine($"CustomerID={item.CustomerID}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    2.4 分組:group

    使用group子句,您可以按指定的鍵分組結果。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 分組一:group
            var db = new SampleDataContext();
            var query =
                from cust in db.Customers
                where cust.City == "London" || cust.City == "Paris"
                group cust by cust.City;
            foreach (var group in query)
            {
                Console.WriteLine(group.Key);
                foreach (var cust in group)
                {
                    Console.WriteLine($"City={cust.City},CustomerID={cust.CustomerID}");
                }
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    在本例中,cust.City是鍵。

    在使用group子句結束查詢時,結果採用列表的列表形式。列表中的每個元素是一個具有Key成員及根據該鍵分組的元素列表的對象。在迴圈訪問生成組

序列的查詢時,您必須使用嵌套的foreach迴圈。外部迴圈用於迴圈訪問每個組,內部迴圈用於迴圈訪問每個組的成員。  

    如果您必須引用組操作的結果,可以使用into關鍵字來創建可進一步查詢的標識符。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 分組二:group
            var db = new SampleDataContext();
            var query =
                from cust in db.Customers
                where cust.City == "London" || cust.City == "Paris"
                group cust by cust.City into custGroup
                where custGroup.Count() > 2
                orderby custGroup.Key
                select custGroup;
            foreach (var group in query)
            {
                Console.WriteLine(group.Key);
                foreach (var cust in group)
                {
                    Console.WriteLine($"City={cust.City},CustomerID={cust.CustomerID}");
                }
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    2.5 聯接:join

    聯接運算創建數據源中沒有顯式建模的序列之間的關聯。例如,您可以執行聯接來查找位於同一地點的所有客戶和經銷商。在LINQ中,join子句始終針對

對象集合而非直接針對資料庫表運行。

    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 聯接:join
            var db = new SampleDataContext();
            var qurey =
                from order in db.Orders
                join cust in db.Customers on order.CustomerID equals cust.CustomerID
                select new { order.OrderID, order.CustomerID, cust.ContactName };
            foreach (var item in qurey.Take(5))
            {
                Console.WriteLine($"OrderID={item.OrderID},CustomerID={item.CustomerID},ContactName={item.ContactName}");
            }
            Console.Read();
            #endregion
        }
    }
View Code

    運行結果如下:

    2.6 選擇(投影):select

    select子句生成查詢結果並指定每個返回的元素的“形狀”或類型。

    例如,您可以指定結果包含的是整個Customer對象、僅一個成員、成員的子集或者某個基於計算或新對象創建的完全不同的結果類型。當select子句生成除源

元素副本以外的內容時,該操作稱為“投影”。

    三、使用 LINQ 進行數據轉換

    語言集成查詢 (LINQ) 不但是檢索數據的利器,而且還是一個功能強大的數據轉換工具。通過使用LINQ查詢,您可以將源序列用作輸入,並採用多種方式修改

它以創建新的輸出序列。您可以通過排序及分組來修改該序列,而不必修改元素本身。但是,LINQ 查詢的最強大的功能是能夠創建新類型。這一功能在select子

句中實現。

    3.1 將多個輸入聯接到一個輸出序列

    /// <summary>
    /// 學生類
    /// </summary>
    class Student
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public string City { get; set; }

        public List<int> Scores { get; set; }
    }

    /// <summary>
    /// 教師類
    /// </summary>
    class Teacher
    {
        public string Name { get; set; }

        public int Age { get; set; }

        public string City { get; set; }
    }      
    
    class Program
    {
        static void Main(string[] args)
        {
            #region LINQ 將多個輸入聯接到一個輸出序列
            //創建第一個數據源
            var students = new List<Student>()
            {
                new Student()
                {
                    Age = 19,
                    City = "廣州",
                    Name = "小A",
                    Scores = new List<int>(){85,88,83,97}
                },
                new Student()
                {
                    Age = 19,
                    City = "深圳",
                    Name = "小B",
                    Scores = new List<int>(){86,80,85,92}
                }
            };

            //創建第二個數據源
            var teachers = new List<Teacher>()
            {
                new Teacher()
                {
                    Age = 30,
                    City = "廣州",
                    Name = "張A"
                },
                new Teacher()
                {
                    Age = 31,
                    City = "廣州",
                    Name = "李A"
                }
            };

            //創建查詢
            var query = 
                (
                    from student in students
                    where student.City == "廣州"
                    select student.Name
                ).Concat
                (
                    from teacher in teachers
                    where teacher.City == "廣州"
                    select teacher.Name
                );

            //執行查詢
            	   

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 場景 Dubbo環境搭建-管理控制台dubbo-admin實現服務監控: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/103624846 Dubbo搭建HelloWorld-搭建服務提供者與服務消費者並完成遠程調用(附代碼下載) ...
  • 這篇文章介紹的內容是關於PHP+Mysql防止SQL註入的方法,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下 方法一: mysql_real_escape_string -- 轉義 SQL 語句中使用的字元串中的特殊字元,並考慮到連接的當前字元集 ! $sql = "select c ...
  • 本篇文章給大家分享的內容是關於如何通過Docker搭建一個swoft開發環境 ,內容很詳細,有需要的朋友可以參考一下,希望可以幫助到你們。Swoft首個基於 Swoole 原生協程的新時代 PHP 高性能協程全棧組件化框架,內置協程網路伺服器及常用的協程客戶端,常駐記憶體,不依賴傳統的 PHP-FPM ...
  • 在項目中經常用到枚舉作為數據字典值和描述的相互轉化。 用法如下: 當枚舉類多了之後,會存在很多重覆的值和描述相互轉化的方法,類似getEnmuByValue和getEnmuByKey。 最近找到一種方法,利用介面、介面預設方法、泛型,實現通用的方法。同類型的枚舉只需要實現該介面即可。 代碼如下: 具 ...
  • 最近項目涉及到一個定時任務的功能,所以去這幾天研究了一下 crontab 的使用方法,按照網上的相關教程順利在自己的電腦上成功開啟了這個功能 Laravel + crontab 添加 crontab 配置 1、執行命令 $ crontab -e 2、添加以下內容( path/to為應用路徑 ),即每 ...
  • 本筆記摘抄自:https://www.cnblogs.com/liqingwen/p/5801249.html,記錄一下學習過程以備後續查用。 “標準查詢運算符”是組成語言集成查詢 (LINQ) 模式的方法,大多數這些方法都在序列上運行,其中的序列是一個對象,其類型實現了IEnumerable<T> ...
  • 一、前言 上一篇大概說了下abp通用樹形模塊如何使用,本篇主要分析下設計思路。 日常開發中會用到很多樹狀結構的數據,比如:產品的多級分類、省市區縣,大多數系統也會用到類似“通用字典/數據字典”的功能,為系統各個地方提下拉框選擇的數據源。abp提供了一個模塊化系統,只要按它的約定就可以實現一個通用的樹 ...
  • 在上一篇文章中,我們已經瞭解過領域驅動設計中一個很核心的對象-聚合。在現實場景中,我們往往需要將聚合持久化到某個地方,或者是從某個地方創建出聚合。此時就會使得領域對象與我們的基礎架構產生緊密的耦合,那麼我們應該怎麼隔絕這一層耦合關係,使它們自身的職責界限更加清晰呢?是的,這就要用到我們今天要講的內容... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...