HOWTO · Csharp
使用 C# 在 LINQ 查詢中按多列分組
這是一篇關於 LINQ 查詢的使用以及我們如何使用 LINQ 查詢按列分組的文章。
本頁內容
本文簡要介紹了使用 C# 進行的 LINQ 查詢。此外,它還討論瞭如何使用 LINQ 查詢按多列對結果進行分組。
如果你已經熟悉 LINQ,則可以安全地跳過介紹部分。
LINQ 簡介
LINQ 是 Language Integrated Query 的縮寫,它為我們提供了一種統一的方法來訪問來自不同資料來源(如資料庫、陣列、XML 等)的資料。它本身可以整合所有查詢。
當開發人員開發應用程式時,他們需要一些除程式語言之外的額外知識來從資料來源獲取資料。例如,如果你的資料來源是資料庫,則程式設計師需要了解 SQL。
同樣,如果資料來源是 XML 文件,程式設計師應該知道如何解析 XML。而使用 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 還跟蹤物件資料的變化並自動同步資料庫中的這些變化。
在專案中建立 LINQ to SQL 元件時,它會自動為所有資料庫表建立類。之後,你需要為連線和資料庫操作編寫程式碼。
假設我們有一個用於儲存公司員工資料的表。表名稱為 Emp,包含以下欄位:Id、Name 和 Email。
要將其用作 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_ID 和 Grade_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