本演练演示如何使用 Visual Basic 语言功能编写 Language-Integrated 查询(LINQ)查询表达式。 该演练演示如何在 Student 对象列表上创建查询、如何运行查询以及如何修改查询。 这些查询包含多个功能,包括对象初始值设定项、本地类型推理和匿名类型。
完成本演练后,即可转到感兴趣的特定 LINQ 提供程序的示例和文档。 LINQ 提供程序包括 LINQ to SQL、LINQ to DataSet 和 LINQ to XML。
创建项目
创建控制台应用程序项目
启动 Visual Studio。
在 “文件” 菜单上,指向 “新建” ,然后单击 “项目” 。
在 “已安装的模板 ”列表中,单击 “Visual Basic”。
在项目类型列表中,单击 “控制台应用程序”。 在“ 名称 ”框中,键入项目的名称,然后单击“ 确定”。
这样就创建了一个项目。 默认情况下,它包含对 System.Core.dll的引用。 此外,项目设计器(Visual Basic) 的“引用”页上的 “导入命名空间” 列表包括 System.Linq 命名空间。
在“编译”页的“项目设计器 (Visual Basic)”中,确保“Option infer”设置为“打开”。
添加内存中的数据源
本演练中查询的数据源是对象列表 Student
。 每个 Student
对象都包含姓名、姓氏、年级以及在学生中的学术排名。
添加数据源
定义类
Student
,并创建类的实例列表。
将新学生添加到学生列表
- 按照方法中的
getStudents
模式将类的另一个实例Student
添加到列表中。 添加学生的操作将引入对象初始值设定项。 有关详细信息,请参阅 对象初始值设定项:命名类型和匿名类型。
创建查询
执行后,在本部分中添加的查询将生成其学术排名排名前十的学生的列表。 由于查询每次都会选择完整的 Student
对象,因此查询结果的类型为 IEnumerable(Of Student)
。 但是,查询类型通常未在查询定义中指定。 相反,编译器使用本地类型推理来确定类型。 有关详细信息,请参阅 本地类型推理。 查询的范围变量 currentStudent
充当对源中每个 Student
实例的引用, students
提供对每个 students
对象属性的访问权限。
创建简单查询
在项目的
Main
方法中找到位置,标记如下:' ****Paste query and query execution code from the walkthrough, ' ****or any code of your own, here in Main.
复制以下代码并将其粘贴到其中。
Dim studentQuery = From currentStudent In students Where currentStudent.Rank <= 10 Select currentStudent
将鼠标指针
studentQuery
放在代码中,验证编译器分配的类型是否为IEnumerable(Of Student)
。
运行查询
该变量 studentQuery
包含查询的定义,而不是运行查询的结果。 运行查询的典型机制是一个 For Each
循环。 通过循环迭代变量访问返回序列中的每个元素。 有关查询执行的详细信息,请参阅 编写第一个 LINQ 查询。
运行查询
在项目中的查询下方添加以下
For Each
循环。For Each studentRecord In studentQuery Console.WriteLine(studentRecord.Last & ", " & studentRecord.First) Next
将鼠标指针悬停在循环控件变量
studentRecord
上以查看其数据类型。 推断studentRecord
的类型为Student
,因为studentQuery
返回的是Student
实例的集合。按 Ctrl+F5 生成并运行应用程序。 记下控制台窗口中的结果。
修改查询
如果查询结果按指定顺序排列,则更容易扫描。 可以根据任何可用字段对返回的序列进行排序。
对结果进行排序
在
Order By
语句和Where
查询语句之间添加以下Select
子句。 该Order By
子句将根据每个学生的姓氏按字母顺序从 A 到 Z 对结果进行排序。Order By currentStudent.Last Ascending
若要按姓氏排序,然后按名字排序,请将这两个字段添加到查询:
Order By currentStudent.Last Ascending, currentStudent.First Ascending
还可以指定
Descending
从 Z 到 A 的顺序。按 Ctrl+F5 生成并运行应用程序。 记下控制台窗口中的结果。
引入本地标识符
添加本节中的代码,以在查询表达式中引入本地标识符。 本地标识符将保留中间结果。 在以下示例中,
name
是一个用于保存学生名字和姓氏串联的标识符。 本地标识符可用于方便,或者通过存储原本需要多次计算的表达式的结果来提高性能。Dim studentQuery2 = From currentStudent In students Let name = currentStudent.Last & ", " & currentStudent.First Where currentStudent.Year = "Senior" And currentStudent.Rank <= 10 Order By name Ascending Select currentStudent ' If you see too many results, comment out the previous ' For Each loop. For Each studentRecord In studentQuery2 Console.WriteLine(studentRecord.Last & ", " & studentRecord.First) Next
按 Ctrl+F5 生成并运行应用程序。 记下控制台窗口中的结果。
在 Select 子句中投影一个字段
添加此部分中的查询和
For Each
循环,以创建一个查询,该查询生成一个序列,其元素与源中的元素不同。 在以下示例中,源是对象的集合Student
,但只返回每个对象的一个成员:姓氏为 Garcia 的学生的名字。 因为currentStudent.First
是字符串,因此studentQuery3
返回的序列的数据类型是IEnumerable(Of String)
字符串序列。 像前面的示例一样,studentQuery3
的数据类型由编译器通过使用本地类型推断来确定。Dim studentQuery3 = From currentStudent In students Where currentStudent.Last = "Garcia" Select currentStudent.First ' If you see too many results, comment out the previous ' For Each loops. For Each studentRecord In studentQuery3 Console.WriteLine(studentRecord) Next
将鼠标指针
studentQuery3
悬停在代码中,以验证分配的类型是否为IEnumerable(Of String)
。按 Ctrl+F5 生成并运行应用程序。 记下控制台窗口中的结果。
在 Select 子句中创建匿名类型
添加本节中的代码,以查看如何在查询中使用匿名类型。 如果要从数据源返回多个字段而不是完整记录(上一个示例中的记录)或单个字段(
currentStudent
First
在上一部分),则可以在查询中使用它们。 无需定义包含要包含在结果中的字段的新命名类型,而是在子句中Select
指定字段,编译器会创建一个匿名类型,并将这些字段用作其属性。 有关详细信息,请参阅匿名类型。以下示例创建一个查询,该查询返回其学术排名在 1 到 10 之间的高级人员的姓名和排名,其学术排名顺序为 1 到 10。 在此示例中,由于
studentQuery4
子句返回的是匿名类型的实例,而匿名类型没有可用名称,因此必须推断Select
的类型。Dim studentQuery4 = From currentStudent In students Where currentStudent.Year = "Senior" And currentStudent.Rank <= 10 Order By currentStudent.Rank Ascending Select currentStudent.First, currentStudent.Last, currentStudent.Rank ' If you see too many results, comment out the previous ' For Each loops. For Each studentRecord In studentQuery4 Console.WriteLine(studentRecord.Last & ", " & studentRecord.First & ": " & studentRecord.Rank) Next
按 Ctrl+F5 生成并运行应用程序。 记下控制台窗口中的结果。
其他示例
现在,你已了解基础知识,下面是一系列其他示例,用于说明 LINQ 查询的灵活性和功能。 每个示例前面都有有关其用途的简要说明。 将鼠标指针悬停在每个查询的查询结果变量上,以查看推断的类型。 使用For Each
循环来生成结果。
' Find all students who are seniors.
Dim q1 = From currentStudent In students
Where currentStudent.Year = "Senior"
Select currentStudent
' Write a For Each loop to execute the query.
For Each q In q1
Console.WriteLine(q.First & " " & q.Last)
Next
' Find all students with a first name beginning with "C".
Dim q2 = From currentStudent In students
Where currentStudent.First.StartsWith("C")
Select currentStudent
' Find all top ranked seniors (rank < 40).
Dim q3 = From currentStudent In students
Where currentStudent.Rank < 40 And currentStudent.Year = "Senior"
Select currentStudent
' Find all seniors with a lower rank than a student who
' is not a senior.
Dim q4 = From student1 In students, student2 In students
Where student1.Year = "Senior" And student2.Year <> "Senior" And
student1.Rank > student2.Rank
Select student1
Distinct
' Retrieve the full names of all students, sorted by last name.
Dim q5 = From currentStudent In students
Order By currentStudent.Last
Select Name = currentStudent.First & " " & currentStudent.Last
' Determine how many students are ranked in the top 20.
Dim q6 = Aggregate currentStudent In students
Where currentStudent.Rank <= 20
Into Count()
' Count the number of different last names in the group of students.
Dim q7 = Aggregate currentStudent In students
Select currentStudent.Last
Distinct
Into Count()
' Create a list box to show the last names of students.
Dim lb As New System.Windows.Forms.ListBox
Dim q8 = From currentStudent In students
Order By currentStudent.Last
Select currentStudent.Last Distinct
For Each nextName As String In q8
lb.Items.Add(nextName)
Next
' Find every process that has a lowercase "h", "l", or "d" in its name.
Dim letters() As String = {"h", "l", "d"}
Dim q9 = From proc In System.Diagnostics.Process.GetProcesses,
letter In letters
Where proc.ProcessName.Contains(letter)
Select proc
For Each proc In q9
Console.WriteLine(proc.ProcessName & ", " & proc.WorkingSet64)
Next
其他信息
熟悉使用查询的基本概念后,即可阅读你感兴趣的特定类型的 LINQ 提供程序的文档和示例: