【vs.net 2008系列-LINQ】 5.演练:在 Visual Basic 中编写查询
本演练将引导您学习新的 Visual Basic 2008 语言功能,并演示如何使用这些功能来编写语言集成查询 (LINQ) 查询表达式。本演练演示如何对一个 Student 对象列表创建查询、如何运行以及如何修改这些查询。这些查询加入了 Visual Basic 2008 的多项新功能,包括对象初始值设定项、局部类型推理和匿名类型。
完成本演练后,就可以转到所关注的特定 LINQ 提供程序的示例和文档。LINQ 提供程序包括 LINQ to SQL、LINQ to DataSet 和 LINQ to XML。
有关视频演示,请参见 Video How to: Writing Queries in Visual Basic(视频帮助:用 Visual Basic 编写查询)。
创建项目 创建面向 .NET Framework 3.5 或更高版本的项目
-
启动 Visual Studio 2008。
-
在“文件”菜单上单击“新建项目”。
-
单击“控制台应用程序”,再单击“确定”。
随即创建一个项目。默认情况下,该项目包含对 System.Core.dll 的引用和适用于 System.Linq 命名空间的 Imports 语句,这两者都是运行 LINQ 查询所必需的。
添加内存中数据源 本演练中查询的数据源是 Student 对象列表。每个 Student 对象都包含名、姓、年级和在全体学生中的学习名次。
添加数据源
-
定义 Student 类,然后创建该类的实例列表。
重要说明:如何:创建项列表中提供了定义 Student 类和创建演练示例所使用的列表所需的代码。您可以复制这些代码并将其粘贴到您的项目中。新代码用于替换在您创建项目时显示的代码。
在学生列表中添加新学生
-
按照 getStudents 方法中的模式将 Student 类的另一个实例添加到列表中。添加学生涉及到对象初始值设定项,这是 Visual Basic 2008 的新功能。有关更多信息,请参见对象初始值设定项:命名类型和匿名类型。
创建查询 执行本节添加的查询时,将生成学习名次位于前十位的学生列表。由于查询每次都选择整个 Student 对象,因此查询结果的类型是 IEnumerable(Of Student)。但是,查询的类型通常不在查询定义中指定,而是由编译器使用局部类型推理来确定。有关更多信息,请参见局部类型推理。查询的范围变量 currentStudent 用作对源 (students) 中每个 Student 实例的引用,以提供对 students 中每个对象属性的访问。
创建简单查询
-
在项目的 Main 方法中找到带如下标记的位置:
Visual Basic' ****Paste query and query execution code from the walkthrough, ' ****or any code of your own, here in Main.
将下面的代码复制并粘贴到此位置。
Visual BasicDim studentQuery = From currentStudent In students _ Where currentStudent.Rank <= 10 _ Select currentStudent
-
将鼠标指针停留在代码中的 studentQuery 上,以验证编译器指定的类型是否为 IEnumerable(Of Student)。
运行查询 变量 studentQuery 包含查询的定义,而非运行查询的结果。运行查询的典型机制是 For Each 循环。通过循环迭代变量来访问返回序列中的每个元素。有关查询执行的更多信息,请参见编写第一个 LINQ 查询 (Visual Basic)。
运行查询
-
将下面的 For Each 循环添加到项目中的查询下面。
Visual BasicFor 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 是保存学生姓和名的串联的标识符。本地标识符可以提供方便,也可以通过存储表达式的结果来避免多次计算,从而提高性能。
Visual BasicDim 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 数据类型的分配由编译器使用局部类型推理来确定。
Visual BasicDim 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 子句中创建匿名类型
-
添加本节中的代码以了解在查询中如何使用匿名类型。匿名类型是 Visual Basic 2008 中的新功能。当您希望从数据源返回多个字段而不是返回完整记录(前面示例中的 currentStudent 记录)或单个字段(前一节中的 First)时,可以在查询中使用匿名类型。可以在 Select 子句中指定要包括在结果中的字段,然后编译器将创建一个以这些字段作为属性的匿名类型,而不需要定义包含这些字段的新命名类型。有关更多信息,请参见匿名类型。
下面的示例创建一个查询,返回学习名次位于 1 和 10 之间的高年级学生的姓名和学习名次,并按学习名次排序。在本例中,必须推断 studentQuery4 的类型,因为 Select 子句返回匿名类型的实例,而匿名类型没有可用的名称。
Visual BasicDim 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 循环可生成结果。
|
Visual Basic
|
' 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 |
浙公网安备 33010602011771号