使用 C# 在 LINQ 查詢中按多列分組

Muhammad Husnain 2023年1月30日 2022年7月18日
  1. LINQ 簡介
  2. 使用 C# 在 LINQ 查詢中按多列分組
使用 C# 在 LINQ 查詢中按多列分組

本文簡要介紹了使用 C# 進行的 LINQ 查詢。此外,它還討論瞭如何使用 LINQ 查詢按多列對結果進行分組。

如果你已經熟悉 LINQ,則可以安全地跳過介紹部分。

LINQ 簡介

LINQ 是 Language Integrated Query 的縮寫,它為我們提供了一種統一的方法來訪問來自不同資料來源(如資料庫、陣列、XML 等)的資料。它本身可以整合所有查詢。

當開發人員開發應用程式時,他們需要一些除程式語言之外的額外知識來從資料來源獲取資料。例如,如果你的資料來源是資料庫,則程式設計師需要了解 SQL。

同樣,如果資料來源是 XML 文件,程式設計師應該知道如何解析 XML。而使用 LINQ,你只需瞭解 LINQ 即可從所有這些資料來源獲取資料。

LINQ 架構

LINQ 到物件

LINQ to Objects 意味著你可以使用 LINQ 查詢從記憶體資料結構中獲取資料。此資料結構可以是使用者定義的,也可以是一些 DotNet 定義的 API。

對資料結構的唯一要求是它應該返回 IEnummerable<T> 型別的集合。

讓我們考慮一個 LINQ to Objects 的示例:

using System;
using System.Linq;

class MyProgram {
   static void Main() {

      string[] list = {"apple", "ball", "aeroplane", "beautiful", "ancient"};

        var starts = from w in list where w.StartsWith("a") select w;
      //Print words
      foreach (var word in starts) {
         Console.WriteLine(word);
      }
   }
}

輸出:

apple
aeroplane
ancient

在上面的程式碼片段中,我們進行了一個 LINQ 查詢來訪問字串陣列中的資料。這樣,這個陣列就可以替換成任何資料結構。

LINQ 查詢的好處是無論你更改後面的資料結構,它的語法都將保持不變。查詢將保持不變;這是 LINQ 提供的統一性。

LINQ 到 SQL

對於 LINQ to ADO.Net,有 3 個子元件。但是,我們將主要關注 LINQ to SQL。

LINQ to SQL 允許我們將關聯式資料庫轉換為物件。它使資料操作更加簡單和快捷。

它遵循的過程是它首先連線到資料庫,將 LINQ 查詢轉換為 SQL 查詢,然後執行這些 SQL 查詢。從 SQL 返回的結果被轉換回 LINQ 構造的物件,然後返回給使用者。

LINQ to SQL 程序

LINQ 還跟蹤物件資料的變化並自動同步資料庫中的這些變化。

在專案中建立 LINQ to SQL 元件時,它會自動為所有資料庫表建立類。之後,你需要為連線和資料庫操作編寫程式碼。

假設我們有一個用於儲存公司員工資料的表。表名稱為 Emp,包含以下欄位:IdNameEmail

要將其用作 LINQ 查詢,請考慮以下程式碼片段:

using System;
using System.Linq;

namespace MyLINQExample {
   class LINQExample {
      static void Main(string[] args) {

         string connectString = System.Configuration.ConfigurationManager.            ConnectionStrings["LinqToSQLDBConnectionString"].ToString();
         LinqToSQLDataContext db = new LinqToSQLDataContext(connectString);
         Emp newEmp = new Emp();
         newEmp.name = "John";
         newEmp.email = "john@abccompany.com";
         newEmp.id = 3;
         //Add this new employee to the database
         db.Emps.InsertOnSubmit(newEmp);

         //To save changes in the database
         db.SubmitChanges();

         //Get the data of inserted employee
         Emp e = db.Emps.FirstOrDefault(e e.name.Equals("John"));

         Console.WriteLine("Emp Id = {0} , Name = {1}, Email = {2}",
                          e.id, e.name, e.email);

         Console.WriteLine("\nPress any key to continue.");
         Console.ReadKey();
      }
   }
}

在上面的程式碼中,我們連線到資料庫,建立了一個資料上下文物件,然後讓我們的查詢在資料庫上執行。

輸出:

Emp Id = 3, Name = John, Email = john@abccompany.com

LINQ 中的連線

與簡單的 SQL 查詢一樣,你也可以使用 LINQ 查詢連線列。當你根據某些條件需要來自不同表的資料時,執行連線操作。

LINQ 提供了 join 運算子,可以輕鬆地連線單個或多個列。考慮我們有以下兩個類:

public class Student{
    public int Stu_ID { get; set; }
    public string Stu_Name { get; set; }
    public int Class_ID { get; set; }
}

public class Grade{
    public int Grade_ID { get; set; }
    public string Grade_Name { get; set; }
}

在驅動函式中,讓我們為每個類建立兩個列表,如下所示:

IList<Student> students_list = new List<Student>() {
    new Student() { Stu_ID = 11, Stu_Name = "ABC", Class_ID =1 },
    new Student() { Stu_ID = 12, Stu_Name = "DEF", Class_ID =1 },
    new Student() { Stu_ID = 13, Stu_Name = "GHI", Class_ID =2 },
    new Student() { Stu_ID = 14, Stu_Name = "JKL", Class_ID =2 },
};

IList<Grade> gradeList = new List<Grade>() {
    new Grade(){ Grade_ID = 1, Grade_Name="Grade 1"},
    new Grade(){ Grade_ID = 2, Grade_Name="Grade 2"},
    new Grade(){ Grade_ID = 3, Grade_Name="Grade 3"}
};

現在,如果我們想得到學生的名字和他們的年級,我們需要連線這兩個表。這些表將分別基於 Class_IDGrade_ID 連線。

連線查詢將如下所示:

var joinResult = from s in student_list
                      join g in gradeList
                      on s.Class_ID equals g.Grade_ID
                      select new {
                                    StuName = s.Stu_Name,
                                    GradeName = g.Grade_Name
                                };

這將產生以下輸出:

ABC Grade 1
DEF Grade 1
GHI Grade 2
JKL Grade 2

使用 C# 在 LINQ 查詢中按多列分組

同樣,我們也可以根據某些屬性對資料進行分組。這是使用 LINQ 查詢中的 GroupBy 子句完成的。

GroupBy 運算子根據鍵值返回所提供集合中元素的子集。IGrouping<TKey, TElement> 物件代表每個組。

此外,GroupBy 方法支援不同的過載方法,因此你可以根據你的要求在方法語法中使用適當的擴充套件方法。

考慮以下程式碼:

List<Student> student_List = new List<Student>() {
    new Student() { Stu_ID = 11, Stu_Name = "ABC", Age =18, Subject ="Arts" },
    new Student() { Stu_ID = 12, Stu_Name = "DEF", Age =19, Subject ="Science" },
    new Student() { Stu_ID = 13, Stu_Name = "GHI", Age =18, Subject ="Arts" },
    new Student() { Stu_ID = 14, Stu_Name = "JKL", Age =19, Subject ="Science" },
    };

假設我們要獲取按年齡分組的學生列表。以下查詢將為我們執行此操作:

var result = from s in student_List
                    group s by s.Age;

foreach (var ageGroups in result)
{
    Console.WriteLine("Age Group: {0}", ageGroups.Key);
    foreach(Student s in ageGroups) // Each group has inner collection
        Console.WriteLine("Student Name: {0}", s.Stu_Name);
}

輸出:

Age Group: 18
Student Name: ABC
Student Name: GHI
Age Group: 19
Student Name: DEF
Student Name: JKL

同樣,我們也可以按多列分組。這是通過以下方式完成的:

var result = from s in student_List
                    group s by  new {s.Age, s.Subject};
foreach (var ageGroups in groupedResult)
        {
            Console.WriteLine("Group: {0}", ageGroups.Key);

            foreach(Student s in ageGroups) // Each group has inner collection
                Console.WriteLine("Student Name: {0}", s.Stu_Name);
        }

此查詢將產生以下輸出:

Group: {Age= 18, Subject="Arts"}
Student Name: ABC
Student Name: GHI
Group: {Age= 19, Subject="Science"}
Student Name: DEF
Student Name: JKL
Muhammad Husnain avatar Muhammad Husnain avatar

Husnain is a professional Software Engineer and a researcher who loves to learn, build, write, and teach. Having worked various jobs in the IT industry, he especially enjoys finding ways to express complex ideas in simple ways through his content. In his free time, Husnain unwinds by thinking about tech fiction to solve problems around him.

LinkedIn

相關文章 - Csharp LINQ