演练:使用 LinqDataSource 和 GridView 控件选择和筛选数据子集
更新:2007 年 11 月
本演练介绍如何使用 LinqDataSource 控件来创建一组不限于单个数据库表中的值的数据。您将使用 LinqDataSource 控件从表中选择数据子集,然后利用所选值计算新值,并要从相关表中检索值。您还将筛选出要返回的记录。然后,使用 GridView 控件显示新值集。
本演练演示了主要从 AdventureWorks 示例数据库的 Product 表中选择值的数据访问。Product 表中包含有其他表的外键的列,您将要从这些相关表中检索数据。
您将使用对象关系设计器创建一个类,以表示包含有这些值的数据库表。LinqDataSource 控件将与所生成的类进行交互以检索并更新数据。
先决条件
若要完成本演练中的过程,您需要:
Visual Studio 2008 或 Visual Web Developer 速成版。
ASP.NET 网站。
SQL Server Express Edition。如果已安装 SQL Server,则可以改用 SQL Server,但必须对某些过程进行小的调整。
安装在您计算机上的 AdventureWorks 数据库。若要下载 AdventureWorks 数据库,请参见 SQL Server 2005 Samples and Sample Databases(SQL Server 2005 示例和示例数据库)。
一个位于网站中的连接到 AdventureWorks 数据库的连接字符串。
创建表示数据库实体的类
若要通过使用 LinqDataSource 控件来处理数据库数据,则需要创建表示数据库实体的类。您可以使用 Visual Studio 2008 中的一个工具来创建这些类。
为 AdventureWorks 数据库表创建类
如果网站中还没有 App_Code 文件夹,请在**“解决方案资源管理器”中右击项目的名称,接着单击“添加 ASP.NET 文件夹”,然后单击“App_Code”**。
右击 App_Code 文件夹,然后单击**“添加新项”**。
显示**“添加新项”**对话框。
在**“Visual Studio 已安装的模板”下选择“LINQ to SQL 类”,将该文件命名为 AdventureWorks.dbml,然后单击“添加”**。
此时将显示**“对象关系设计器”**。
在**“服务器资源管理器”中,将 Product (Production) 表拖到“对象关系设计器”**窗口中。
Product (Production) 表及其列在设计器窗口中以名称为 Product 的实体表示。
将 ProductSubCategory 表和 UnitMeasure 表拖到设计器窗口中。
这些表及其列在设计器窗口中以实体表示。Product 表和这两个相关表之间的关系以虚线表示。
保存 AdventureWorks.dbml 文件。
在**“解决方案资源管理器”**中,打开 AdventureWorks.designer.cs 或 AdventureWorks.designer.vb 文件。
该文件具有名称为 AdventureWorksDataContext、Product、ProductSubCategory 和 UnitMeasure 的类。Product 类包含有名称为 ProductSubcategory、UnitMeasure 和 UnitMeasure1 的属性。这些属性已经利用 AssociationAttribute 属性标记为了外键。它们可返回表示 ProductSubCategory 表和 UnitMeasure 表的对象。
UnitMeasure 属性表示 SizeUnitMeasureCode 列中的值的外键关系。UnitMeasure1 属性表示 WeightUnitMeasureCode 列的外键。
选择要检索的列
如果您不为 Select 属性指定值,则 LinqDataSource 控件将会返回表示数据库表的类的所有属性(列)。
使用 LinqDataSource 控件检索数据子集
在 Visual Studio 中,创建一个新的 ASP.NET 网页,然后切换到“源”视图。
从工具箱的**“数据”**选项卡中,将 LinqDataSource 控件拖到网页上的 form 元素内。
可以将 ID 属性保留为 LinqDataSource1。
将 ContextTypeName 属性设置为 AdventureWorksDataContext。
AdventureWorksDataContext 类是表示 AdventureWorks 数据库的数据上下文类。它包含数据库中每个表的属性。
将 TableName 属性设置为 Products。
按照以下方式设置 Select 属性:
new(Name, Size, StandardCost, ListPrice, DaysToManufacture)
通过设置 Select 属性,您可以对从 Products 类检索的属性进行限制。如果从类中选择多个属性,则必须将这些属性用 new 运算符括起来。这是因为 LinqDataSource 控件不会返回 TableName 属性中指定的类的实例。相反,它会返回一个动态创建的、仅包含这些属性的类的实例。
筛选要检索的记录
如果不为 Where 属性指定值,则 LinqDataSource 控件将会返回数据库表中的所有记录。您可以通过设置 Where 属性来筛选要返回的记录。您可以利用静态值(如 ListPrice > 0)进行筛选,以仅返回其所拥有 ListPrice > 0 属性值大于零的记录。您还可通过向 WhereParameters 集合添加参数,来在运行时赋值。
使用 LinqDataSource 控件在运行时筛选数据
将 DropDownList 控件添加到网页,并将其 AutoPostBack 属性设置为 true。
保留默认名称 DropDownList1。
向 DropDownList1 控件添加四个列表项,然后将它们的值分别设置为 0、25、100 和 400。
在 LinqDataSource 控件的开始标记和结束标记之间添加一个 WhereParameters 元素。
将 ControlParameter 控件添加到 WhereParameters 集合中。
将 ControlParameter 控件的 ControlID 属性设置为 DropDownList1,将 Name 属性设置为 SelectedPrice,并将 Type 属性设置为 Int32。
在运行时,SelectedPrice 参数将包含从 DropDownList1 中选择的值。
将 Where 属性设置为 ListPrice > @SelectedPrice,以便只选择其 ListPrice 值大于用户所选值的记录。
下面的代码示例演示 DropDownList 和 LinqDataSource 控件的声明性标记。
<asp:DropDownList AutoPostBack="true" ID="DropDownList1" runat="server"> <asp:ListItem Value="0"></asp:ListItem> <asp:ListItem Value="25"></asp:ListItem> <asp:ListItem Value="100"></asp:ListItem> <asp:ListItem Value="400"></asp:ListItem> </asp:DropDownList> <asp:LinqDataSource ContextTypeName="AdventureWorksDataContext" TableName="Products" Where="ListPrice > @SelectedPrice" Select="new(Name, Size, StandardCost, ListPrice, DaysToManufacture)" ID="LinqDataSource1" runat="server"> <WhereParameters> <asp:ControlParameter Name="SelectedPrice" DefaultValue="0" ControlID="DropDownList1" Type="Int32" /> </WhereParameters> </asp:LinqDataSource>
添加显示数据的控件
您现在可以添加一个 GridView 控件并将其绑定到 LinqDataSource 控件。GridView 控件使用户能够查看由 LinqDataSource 控件管理的数据行。这样,用户便能够对数据进行排序并按页查看。
在 GridView 控件中显示数据子集
在**“工具箱”的“数据”**选项卡中,双击 GridView 控件以将其添加到页面中。
将 GridView 控件的 DataSourceID 属性设置为 LinqDataSource1。
这会将 GridView 控件绑定到 LinqDataSource 控件返回的数据。
将 AllowPaging 和 AllowSorting 属性设置为 true。
如果要使用 LinqDataSource 控件进行排序和分页,则 AutoSort 和 AutoPage 属性必须为 true。默认情况下,这两个值都为 true。
将 AutoGenerateColumns 属性设置为 false。
若要指定列的顺序,则请为您在 LinqDataSource 控件的 Where 属性中指定的每个属性(Name、Size、StandardCost、ListPrice 和 DaysToManufacture)创建一个 BoundField 控件。
下面的示例演示 GridView 控件的声明性标记。
<asp:GridView AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false" DataSourceID="LinqDataSource1" ID="GridView1" runat="server"> <Columns> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /> <asp:BoundField DataField="Size" HeaderText="Size" SortExpression="Size" /> <asp:BoundField DataField="StandardCost" HeaderText="Standard Cost" SortExpression="StandardCost" /> <asp:BoundField DataField="ListPrice" HeaderText="List Price" SortExpression="ListPrice" /> <asp:BoundField DataField="DaysToManufacture" HeaderText="Days To Manufacture" SortExpression="DaysToManufacture" /> </Columns> </asp:GridView>
保存页,然后按 Ctrl+F5 以在浏览器中查看该页。
GridView 控件将显示 Product 表中当前记录的列。您可以通过单击列标题来对记录进行排序,还可通过单击页码来按页查看记录。
使用数据源值计算新值
除了从数据库表选择值之外,您还可以计算新值。如果要显示只能通过对来自数据源的值执行计算才能派生的值,则您就可能需要进行此操作。然后,您就可以在 GridView 控件中显示这些值了。
计算并显示来自数据源的新值
将 Select 属性的值更改为下列值:
new(Name, Size, StandardCost, ListPrice, ListPrice - StandardCost as PriceDifference, DaysToManufacture / 5.0 as WeeksToManufacture)
数据库中并不存在其他值(PriceDifference 和 WeeksToManufacture)。仅当对数据库中的值执行计算后才可显示这些值。
在 GridView 控件中,为 PriceDifference 和 WeeksToManufacture 列添加 BoundField 控件,并移除 DaysToManufacture 的 BoundField 控件。
下面的示例演示计算的 BoundField 控件的声明性标记。
<asp:BoundField DataField="PriceDifference" HeaderText="Price Difference" SortExpression="Price Difference" /> <asp:BoundField DataField="WeeksToManufacture" HeaderText="Weeks To Manufacture" SortExpression="WeeksToManufacture" />
保存页,然后按 Ctrl+F5 以在浏览器中查看该页。
GridView 控件将显示 Product 表中的当前记录的列和计算出的值的列。
从相关表选择值
您不但可以从表检索值,还可从具有一个 LinqDataSource 控件的任何相关表检索值。当一个表与其他表具有外键关系时,对象关系设计器会生成一个包含每个相关表的属性的实体类。这些属性可返回表示相关表的对象。返回的对象包含相关表中所有列的属性。您可以通过访问类中表示相关表的对象来从相关表选择值。
从相关表检索数据
将 LinqDataSource 控件的 Select 属性设置为下列值:
new(Name, Size, UnitMeasure.Name as SizeMeasureName, Weight, UnitMeasure1.Name as WeightMeasureName, ProductSubcategory.Name as SubCategoryName)
SizeMeasureName、WeightMeasureName 和 SubCategoryName 属性包含有与 Products 表具有外键关系的表的值。
若只返回具有大小或重量度量单位的产品,请将 Where 属性设置为:
WeightUnitMeasureCode != null || SizeUnitMeasureCode != null
对这些值进行筛选可阐释 LinqDataSource 控件是如何管理外键关系的。|| 运算符可执行逻辑 OR 运算。因此,仅会返回拥有至少赋予给一个外键的值的记录。
下面的示例演示 LinqDataSource 控件的声明性标记。
<asp:LinqDataSource ContextTypeName="AdventureWorksDataContext" TableName="Products" Where="WeightUnitMeasureCode != null || SizeUnitMeasureCode != null" Select="new(Name, Size, UnitMeasure.Name as SizeMeasureName, Weight, UnitMeasure1.Name as WeightMeasureName, ProductSubCategory.Name as SubCategoryName)" ID="LinqDataSource1" runat="server"> </asp:LinqDataSource>
在 GridView 控件中,为每个列添加 BoundField 控件,以便显示。这些列为 Name、Size、SizeMeasureName、Weight、WeightMeasureName 和 SubCategoryName。
下面的示例演示 GridView 控件的声明性标记。
<asp:GridView AllowPaging="true" AllowSorting="true" AutoGenerateColumns="false" DataSourceID="LinqDataSource1" ID="GridView1" runat="server"> <Columns> <asp:BoundField DataField="Name" HeaderText="Name" SortExpression="Name" /> <asp:BoundField DataField="Size" HeaderText="Size" SortExpression="Size" /> <asp:BoundField DataField="SizeMeasureName" HeaderText="Size Unit of Measurement" SortExpression="SizeMeasureName" /> <asp:BoundField DataField="Weight" HeaderText="Weight" SortExpression="Weight" /> <asp:BoundField DataField="WeightMeasureName" HeaderText="Weight Unit of Measurement" SortExpression="WeightMeasureName" /> <asp:BoundField DataField="SubCategoryName" HeaderText="Subcategory Name" SortExpression="SubCategoryName" /> </Columns> </asp:GridView>
保存页,然后按 Ctrl+F5 以在浏览器中查看该页。
GridView 控件将显示来自 Product、ProductSubCategory 和 UnitMeasure 表的值。您可以对记录进行排序并按页查看。
后续步骤
在本演练中,您学习了如何使用 LinqDataSource 控件来自定义查询中要返回的列和记录。您可以向 LinqDataSource 控件添加更多功能,例如:
启用更新、插入和删除操作。有关更多信息,请参见 演练:使用 LinqDataSource 和 DetailsView 控件检索、更新、插入和删除数据。
将数据分组以及聚合值,如计算列值的总和或平均值。有关更多信息,请参见 如何:使用 LinqDataSource 控件对数据进行分组和聚合。
确保从您检索数据库中的数据,到数据被更新或删除的这段时间内,这些数据不会发生更改。有关更多信息,请参见 演练:对 LinqDataSource 控件使用时间戳以检查数据完整性。