在 ASP.NET 网页中使用语言集成查询 (LINQ) 访问数据 – 第 1 部分






1.73/5 (5投票s)
在 ASP.NET 中使用 LinqDataSource 控件访问各种类型的数据。
引言
本文包含两部分。第 1 部分介绍 LINQ 和 ASP.NET 中的 LinqDataSource
控件,并描述如何定义和检索内存中的数据集合以及如何在网页中显示数据。第 2 部分解释如何使用对象关系设计器创建实体类来表示 SQL Server 数据库和表,并使用 LinqDataSource
控件在网页中显示数据。
LINQ 简介
语言集成查询 (LINQ) 是一种查询语法,它定义了一组查询运算符,允许以声明性方式在任何基于 .NET 的编程语言中表达遍历、过滤和投影操作。它提供了一个统一的编程模型,用于查询和更新来自不同类型数据源的数据,并将数据功能直接扩展到 C# 和 Visual Basic 语言中。LINQ 通过将面向对象编程的原则应用于关系数据,简化了面向对象编程和关系数据之间的交互。
随着 LINQ 的出现,一个突破性的新概念——“查询”——作为 C# 和 Visual Basic 中的一流语言构造被引入。LINQ 简化了您处理数据查询的方式。LINQ 为您提供了一个统一的声明性语法模型来查询任何数据源,包括 XML 文档、SQL Server 数据库、ADO.NET 数据集、内存中集合或任何其他选择支持 LINQ 的远程或本地数据源。语言集成查询是强类型的,并且可以使用设计器工具创建对象关系映射。现在开发人员更容易在编译时捕获错误;它还支持 Intellisense 和调试。
示例查询
查询是检索数据源中数据的表达式。所有 LINQ 查询操作都包含三个基本动作:获取数据源、创建查询和执行查询。
在 LINQ 中,查询的执行与查询本身是隔离的,因此仅仅通过创建查询无法检索数据。
在以下示例中,一个查询从整数数组中检索偶数。输出将是:0,2,4,6,8,10。
// Data source.
int[] numbers = new int[10] { 0, 1, 2, 3, 4, 5, 6 ,8,9,10};
// Query creation.
IEnumerable<int> numQuery =
from num in numbers where (num % 2) == 0 select num;
// Query execution.
foreach (int j in numQuery)
{
Console.Write("{0,1} ", j);
}
ASP.NET 中的 LinqDataSource 控件
正如许多熟悉 ASP.NET 2.0 中各种 DataSource 控件的人所知,ASP.NET 的 2008 版本包含一个新的 DataSource 控件,名为 LinqDataSource
。LinqDataSource
控件使我们能够使用语言集成查询 (LINQ) 从内存中的数据集合或 SQL Server 数据库表中检索和更新数据。它会自动生成用于选择、更新、删除和插入操作的数据命令,您无需手动创建它们。
此控件有两个主要属性
ContextTypeName
表示包含数据集合的类型对象的名称。TableName
表示返回数据集合的公共字段或属性的名称,或者在数据库访问的情况下表示表名。
演练 1:使用 LinqDataSource 控件连接内存中的数据集合并执行查询以在 ASP.NET 页面中显示数据
打开 Visual Studio 2008 并创建一个新的网站项目。
向项目的 App_Code 文件夹添加一个新类文件。定义向控件提供数据的类并编写 LINQ 查询以从中检索数据。
public class Student {
public string First { get; set; }
public string Last { get; set; }
public int ID { get; set; }
public List<int> Scores;
}
public class StudentData
{
static List<Student> students = new List<Student>
{
new Student {First="Svetlana",
Last="Omelchenko", ID=111,
Scores= new List<int> {97, 92, 81, 60}},
new Student {First="Claire",
Last="O’Donnell", ID=112,
Scores= new List<int> {75, 84, 91, 39}},
new Student {First="Sven",
Last="Mortensen", ID=113,
Scores= new List<int> {88, 94, 65, 91}},
new Student {First="Cesar", Last="Garcia",
ID=114, Scores= new List<int> {97, 89, 85, 82}},
new Student {First="Debra", Last="Garcia",
ID=115, Scores= new List<int> {35, 72, 91, 70}},
new Student {First="Fadi", Last="Fakhouri",
ID=116, Scores= new List<int> {99, 86, 90, 94}},
new Student {First="Hanying", Last="Feng",
ID=117, Scores= new List<int> {93, 92, 80, 87}},
new Student {First="Hugo", Last="Garcia",
ID=118, Scores= new List<int> {92, 90, 83, 78}},
new Student {First="Lance", Last="Tucker",
ID=119, Scores= new List<int> {68, 79, 88, 92}},
new Student {First="Terry", Last="Adams",
ID=120, Scores= new List<int> {99, 82, 81, 79}},
new Student {First="Eugene", Last="Zabokritski",
ID=121, Scores= new List<int> {96, 85, 91, 60}},
new Student {First="Michael", Last="Tucker",
ID=122, Scores= new List<int> {94, 92, 91, 91} }
};
您刚刚添加了一个 Student
类并在类文件中初始化了一个学生列表。查询的数据源是一个简单的 Student
对象列表。每个学生记录都包含名字、姓氏和代表其课程考试成绩的整数数组。
创建查询
您可以创建许多查询来从数据源检索数据,在本文中,我创建了一些查询用于演示目的。每个查询都分配给一个公共属性或字段,以便在网页中的 LinqDataSource
控件中使用。
IEnumerable<StudentAverage> 类型的查询
public class StudentAverage
{
public int ID;
public string First;
public string Last;
public double ScoreAverage;
}
public IEnumerable<StudentAverage> studentAverageMarks =
from student in StudentData.students
where student.Scores[0] > 90
select new StudentAverage { ID=student.ID, First=student.First,
Last=student.Last, ScoreAverage = student.Scores.Average()};
声明一个新类型 StudentAverage
,它由 ID
、First
、Last
和 ScoreAverage
字段组成。此查询返回学生列表及其平均分数。
IEnumerable<int> 类型的查询
public static int studentID;
public IEnumerable<int> GetStudentTotal = from student
in StudentData.students where student.ID ==
StudentData.studentID select student.Scores.Sum();
声明另一个公共属性,该属性返回一个包含查询结果的 int
类型集合。此查询检索特定学生所有分数的总和,并在 where 子句中使用条件。用户将在运行时为参数 studentID
提供数据。
public IEnumerable<int>
GetStudentList = from student in StudentData.students
select student.ID;
GetStudentList
是添加到类中的另一个属性,它存储查询的结果。此查询返回 Student.ID
的集合。
隐式类型(匿名类型)的查询
public IEnumerable GetData
{
get
{
var studentMarks = from student in StudentData.students where
student.ID > 110 select new { ID = student.ID,
First = student.First, Last = student.Last,
ScoreTotal = student.Scores.Sum() };
foreach (var s in studentMarks)
yield return s.ID + ", " + s.Last + ", " +
s.First + ", " + s.ScoreTotal;
}
}
现在,您刚刚添加了一个公共属性,它将查询结果作为学生分数数据的集合返回。请注意,查询涉及一个匿名类型,其中包含 ID
、First
、Last
和 ScoreTotal
等字段。查询返回隐式类型 var,它使用迭代器返回集合中的元素。
至此,您的数据源和查询已准备就绪,可供网页的数据绑定控件访问。
设计网页以查看数据
为了演示 LINQ 数据源的用法并在网页上查看数据,页面布局设计为三个部分。
第 1 节:查看学生详细信息,例如 ID、名字、姓氏和平均分数。此视图执行本文前面定义的查询 1,studentAverageMarks
。
从工具箱的数据选项卡中将一个 LinqDataSource
控件(ID
=LinqDataSource1
)拖到页面中,并按照以下“配置数据源向导”中的说明,将其配置为访问您刚刚在项目中创建的数据源和查询。
- 选择“StudentData”作为上下文对象。
- 在数据选择中选择“studentAverageMarks”作为表,并勾选选择列表中出现的所有字段。
- 单击“完成”按钮以完成
LinqDataSource
控件的配置。
从工具箱的数据选项卡中将一个 GridView
控件(ID
=GridView1
)拖到页面中,并将 DataSource
属性设置为 LinqDataSource1
。
第 2 节:查看下拉列表中选定学生 ID 的总分数。此部分执行本文前面定义的查询 2,GetStudentTotal
。
从工具箱的数据选项卡中将一个 LinqDataSource
控件(ID
=LinqDataSource2
)拖到页面中,并按照以下“配置数据源向导”中的说明,将其配置为访问您刚刚在项目中创建的数据源和查询。
- 选择“StudentData”作为上下文对象。
- 在数据选择中选择“GetStudentList”作为表,并勾选选择列表中出现的字段。(图3)
- 单击“完成”按钮以完成
LinqDataSource
控件的配置。
将一个 DropDownList
控件(ID
=DropDownList1
)拖到页面中,并将 DataSource
属性设置为 LinqDataSource2
。请记住勾选启用此控件自动回发行为的复选框。
在页面中放置 TextBox
和 Label
控件,并将以下代码添加到 DropDownList1
的 SelectedIndexChanged
事件处理程序中。
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
StudentData sd = new StudentData();
StudentData.studentID = Convert.ToInt32(DropDownList1.SelectedItem.Text);
TextBox2.Text = Convert.ToString(sd.GetStudentTotal.ToList<int>()[0]);
}
第 3 节:查看学生详细信息,例如学生 ID、名字、姓氏和总分数。此视图执行查询 3,studentMarks
,该查询由本文前面定义的公共属性 GetData
返回。
从工具箱的数据选项卡中将一个 LinqDataSource
控件(ID
=LinqDataSource3
)拖到页面中,并将其配置为访问您刚刚在项目中创建的数据源和查询。
- 选择“StudentData”作为上下文对象。
- 在数据选择中选择“GetData”作为表,并勾选选择列表中出现的所有字段。
- 单击“完成”按钮以完成
LinqDataSource
控件的配置。
从工具箱的数据选项卡中将一个 ListBox
控件(ID
=ListBox1
)拖到页面中,并将 DataSource
属性设置为 LinqDataSource3
。
就是这样。现在,运行网页并查看如下所示的输出。
摘要
本文的第一部分演示了如何定义和连接内存中的数据源,并解释了定义和执行数据集合查询的各种方法。现在,邀请您阅读本文的第二部分,该部分定义了数据库对象的实体类,并编写和执行数据库表对象的 LINQ 查询。