使用 C# 在 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
相关文章
在 C# 中将 List<string>转换为字符串
发布时间:2024/03/16 浏览次数:198 分类:编程语言
-
在 C# 中,有两种主要方法可用于将 List
转换为字符串变量,Linq 方法和 String.Join()函数。
在 C# 中将 List<string>转换为字符串
发布时间:2024/03/16 浏览次数:171 分类:编程语言
-
在 C# 中,有两种主要方法可用于将 List
转换为字符串变量,Linq 方法和 String.Join()函数。
在 C# 中将 List<string>转换为字符串
发布时间:2024/03/16 浏览次数:187 分类:编程语言
-
在 C# 中,有两种主要方法可用于将 List
转换为字符串变量,Linq 方法和 String.Join()函数。
在 C# 中发出 HTTP POST Web 请求
发布时间:2024/02/04 浏览次数:131 分类:编程语言
-
在 C# 中,可以使用 3 种主要方法来发出 HTTP POST Web 请求:WebClient 类,HttpWebRequest 类和 HttpClient 类。本教程将讨论在 C# 中发出 HTTP POST Web 请求的方法。使用 C# 中的 WebClient 类发出 HTTP POST Web 请求
在 C# 中运行命令提示符命令
发布时间:2024/02/04 浏览次数:130 分类:编程语言
-
Process 类可用于在 C# 中运行命令提示符命令。在 C# 中使用 Process.Start() 函数运行命令提示符命令
在 C# 中调整图像大小
发布时间:2024/02/04 浏览次数:203 分类:编程语言
-
有两种主要方法可用于在 C# 中调整图像的大小,Bitmap 类构造函数和 graphics.DrawImage()函数。在本教程中,我们将讨论在C#中调整图像大小的方法。我们将带您完成整个过程,从加载原始图像到保
在 C# 中下载图片
发布时间:2024/02/04 浏览次数:138 分类:编程语言
-
有 3 种主要方法可用于下载 C# 中的图片,WebClient.DownloadFile()函数,Bitmap 类和 Image.FromStream()函数。在 C# 中使用 WebClient 类下载图片 WebClient 类提供了用于向 C# 中的 URL 发送数据和从 URL 接收数据
在 C# 中使用秒表
发布时间:2024/02/04 浏览次数:139 分类:编程语言
-
我们可以使用 Stopwatch 类来计算 C# 中的经过时间。使用 C# 中的秒表类计算经过时间 Stopwatch 类在 C# 中准确测量经过的时间。
在 C# 中获取可执行路径
发布时间:2024/02/04 浏览次数:200 分类:编程语言
-
有 3 种主要方法可用于获取 C# 中程序的可执行路径,即 Assembly 类,AppDomain 类和 Path 类。本教程将介绍获取 C# 代码的可执行路径的方法。使用 C# 中的 Assembly 类获取可执行路径