使用 SqlDataSource 控件查询数据

本文档是 Visual C# 教程 (切换到 Visual Basic 教程)

在前面的教程中,我们使用 ObjectDataSource 控件完全分离了表示层和数据访问层。从本教程开始,我们将学习如何在不需要严格分离表示层和数据访问层的简单应用中使用 SqlDataSource 控件。

« 前一篇教程  |  下一篇教程 »

简介

我们目前探讨的所有教程均使用分层结构,包括表示层,业务逻辑层和数据访问层。我们已经在第一个教程(创建数据访问层)中对数据访问层 ( DAL ) 做了详细的探讨,在第二个教程(创建业务逻辑层)中对业务逻辑层做了详细的探讨。从使用 ObjectDataSource 显示数据 教程开始,我们探讨了如何使用 ASP.NET 2.0 的新增 ObjectDataSource 控件从表示层相互连接各层机构。

目前为止, 我们在所有教材中使用这种结构来处理数据,然而您也可以跳过这种结构从 ASP.NET 页面直接 访问、插入、更新和删除数据库数据。这样做将直接将特定数据库查询和业务逻辑置于 web 页面中。对于规模较大或者非常复杂的应用程序来说,设计、实现和使用分层结构对应用程序的成功、可更新性和可维护性来说至关重要。但是,开发稳健的结构对特别简单的一次性程序来说似乎完全没有必要。

ASP.NET 2.0 提供有5 个内置的数据源控件—— SqlDataSourceAccessDataSourceObjectDataSourceXmlDataSource 、和SiteMapDataSource 。SqlDataSource 可用于从关系数据库中(包括 Microsoft SQL Server 、 Microsoft Access 、 Oracle 、 MySQL 和其他数据库)直接访问和修改数据。在本教程和接下来的三个教程中,我们将探讨如何使用 SqlDataSource 控件,如何查询和过滤数据库数据,以及如何使用 SqlDataSource 来插入、更新和删除数据。

图1 :ASP.NET 2.0 包含五个内置数据源控件

比较ObjectDataSource 和SqlDataSource

从概念上来说,ObjectDataSource 和 SqlDataSource 控件只是数据代理。正如使用 ObjectDataSource 显示数据 教程中我们讨论过的一样 ,ObjectDataSource 有表示对象类型的属性,从基本对象类型提供选择、插入、更新和删除的数据和方法。一旦配置了 ObjectDataSource 的属性,Web 数据控件(如 GridView 、DetailsView 或 DataList )则可绑定到控件,使用 ObjectDataSource 的 Select() 、Insert() 、Delete() 和 Update() 与基本结构进行交互。

SqlDataSource 提供了相同的功能,但它操作关系数据库而不是对象库。使用 SqlDataSource ,我们必须指定数据库链接字符串和随机 SQL 查询或者存储过程来插入、更新、删除和检索数据。当调用SqlDataSource 的 Select() 、Insert() 、Update() 和 Delete() 方法时,它们将连接至指定的数据库并进行适当的SQL 查询。这些方法完成繁琐的连接数据库、完成查询和返回结果等工作,如下图所示。

图2 :SqlDataSource 充当数据库的代理

注意:在本教程中,我们主要讨论从数据库中检索数据。在使用 SqlDataSource控件插入、更新和删除数据 教程中,我们将探讨如何配置 SqlDataSource ,使之支持插入、更新和删除。

SqlDataSource 和 AccessDataSource 控件

除了SqlDataSource 控件之外,ASP.NET 2.0 还包含一个 AccessDataSource 控件。这两种控件使很多初次使用 ASP.NET 2.0 的开发人员怀疑 AccessDataSource 控件是专门适用于 Microsoft Access ,而 SqlDataSource 控件则专门适用于 Microsoft SQL Server 。AccessDataSource 专门适用于 Microsoft Access ,而 SqlDataSource 控件则可以应用于所有可通过 .NET 访问的任意关系数据库。包括任何 OleDb- 或者 ODBC 兼容的数据存储库,例如 Microsoft SQL Server 、 Microsoft Access 、 Oracle 、 Informix 、 MySQL 、 PostgreSQL 和其它的数据库。

AccessDataSource 和 SqlDataSource 控件之间的唯一区别在于数据库连接信息是如何指定的。AccessDataSource 控件仅仅需要 Access 数据库文件的文件路径。而 SqlDataSource 则需要完整的连接字段。

步骤1 :创建SqlDataSource Web 页

在我们探讨如何使用 SqlDataSource 控件直接处理数据库数据之前,我们首先花费几分钟时间在我们的网站中创建一个ASP.NET 页,此页面我们将在本教程和下面的三个教程中需要使用。首先,添加一个名为 SqlDataSource 的新文件夹。接下来,将以下 ASP.NET 页面添加到该文件夹,确保每个页面与 Site.master 母版页相关联:

  • Default.aspx
  • Querying.aspx
  • ParameterizedQueries.aspx
  • InsertUpdateDelete.aspx
  • OptimisticConcurrency.aspx

图3 :为SqlDataSource 相关教程添加ASP.NET 页

和其他文件夹一样,SqlDataSource 文件夹中的 Default.aspx 将列出文件夹中的教程。回想一下,SectionLevelTutorialListing.ascx 用户控件提供本功能。因此,您可以从 Solution Explorer 中将此 User 控件拖拽到页面设计视图。

图4 :向 Default.aspx 添加 SectionLevelTutorialListing.ascx 用户控件

最后,将页面按条目添加到 Web.sitemap 文件中。具体而言,在“为 DataList 和 Repeater 添加定制按钮”之后添加下列标记 <siteMapNode> :

<siteMapNode url="~/SqlDataSource/Default.aspx"
    title="Using the SqlDataSource Control"
    description="Work directly with database data using the SqlDataSource control.">
    <siteMapNode url="~/SqlDataSource/Querying.aspx" title="Retrieving Database Data"
        description="Examines how to query data from a database that can then be
                     displayed  through a data Web control."/>
    <siteMapNode url="~/SqlDataSource/ParameterizedQueries.aspx"
        title="Parameterized Queries"
        description="Learn how to specify parameterized WHERE clauses in the
                     SqlDataSource's SELECT statement." />
    <siteMapNode url="~/SqlDataSource/InsertUpdateDelete.aspx"
        title="Inserting, Updating, and Deleting Database Data"
        description="See how to configure the SqlDataSource to include INSERT, UPDATE,
                      and DELETE statements." />
    <siteMapNode url="~/SqlDataSource/OptimisticConcurrency.aspx"
        title="Using Optimistic Concurrency"
        description="Explore how to augment the SqlDataSource to include support for
                     optimistic concurrency." />
</siteMapNode>

更新 Web.sitemap 后,花点时间用浏览器查看一下教程网站。现在,左边的菜单包含用于编辑、插入和删除教程的各项。

图5 :现在,站点地图包含了 SqlDataSource 教程的条目。

步骤2 :添加和配置 SqlDataSource 控件

首先,在 SqlDataSource 文件夹中打开 Querying.aspx 页,切换到设计视图。从工具栏中将一个 SqlDataSource 控件拖拽到设计器中,并设置其 ID 为 ProductsDataSource 。跟 ObjectDataSource 一样,SqlDataSource 并不产生任何显示输出,因此在设计视图中显示为一个灰色框。要配置 SqlDataSource ,从 SqlDataSource 的智能标记单击配置数据源链接。

图6 :从 SqlDataSource 的智能标记单击配置数据源链接

此操作将显示SqlDataSource 控件的配置数据源向导。尽管向导步骤与 O bjectDataSource 控件的步骤有所区别,但是最终目的是一样的 —— 提供如何通过数据源检索、插入、更新和删除数据的详细情况。对于 SqlDataSource 而言,需要指定使用的基础数据库并提供随机的 SQL 语句或者存储过程。

向导第一步提示我们输入数据库。下拉列表包括  web 应用程序 App_Data 文件夹中的数据库和在服务器资源管理器中添加到数据连接节点的数据库。 由于我们已经为  NORTHWIND.MDF 数据库在 App_Data 文件夹中向工程的 Web 配置文件添加了一个连接字符串,因此下拉列表包含一个此连接字符串的引用 —— NORTHWINDConnectionString 。从下拉列表选择此项,单击下一步。

图7 :从下拉列表选择 NORTHWINDConnectionString

在选择数据库之后,向导将要求查询返回数据。我们既可以指定表的列、视图、或者输入一条定制 SQL 语句,也可以指定存储过程。您可以选择“指定定制 SQL 语句或存储过程”或者“从表或视图指定列”。

注意:在第一个示例中,我们使用“从表或视图指定列或视图”选项。在此教程中,我们随后将返回向导并探讨“指定定制 SQL 语句或存储过程”选项。

图 8 显示了选择“从表或视图指定列”单选按钮时的“配置Select  语句”屏幕。下拉列表包含了 Northwind数据的表和视图的集合,在下拉列表的下面,用复选框列表,列出了被选中的表或视图的字段 。在此示例中,我们将从 Products 表返回 ProductID 、 ProductName 和 UnitPrice 列。图8 显示了作出这些选择之后,向导自动生成 SQL 语句 —— SELECT [ProductID] 、[ProductName] 和[UnitPrice] FROM [Products] 。

图8 :从 Products 表返回数据

将向导配置为从 Products 表返回 ProductID 、ProductName 和 UnitPrice 列之后。最后一个屏幕将提供检查前面步骤配置的查询结果的机会。单击 Test Query 按钮,执行配置的 SELECT 语句,在网格中显示结果。

图9 :单击 Test Query 按钮,查看您的 SELECT 查询

完成向导,请单击 Finish 。

类似于 ObjectDataSource ,SqlDataSource 向导只是给控件的属性(只是ConnectionStringSelectCommand )分配值。在完成向导之后,SqlDataSource 控件的声明式标记应与下列类似:

<asp:SqlDataSource ID="ProductsDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]">
</asp:SqlDataSource>

ConnectionString 属性提供了如何连接到数据库的信息。此属性用一个完整的连接字符串进行赋值,或者在 Web.config 中定义连接字符串。要在 Web.config 中引用连接字符串值,可以使用 <%$ expressionPrefix:expressionValue %> 语法。通常而言, expressionPrefix 为“ ConnectionStrings ”,expressionValue 为 Web.config 的 <connectionStrings> 部分中的连接字符串名称。而且,此语法可用于从资源文中件引用 <appSettings> 中的 内容。有关此语法的更多信息,请参见 ASP.NET 表达式概述

SelectCommand 属性指定了用于返回数据的ad-hoc SQL 语句,或者存储过程。

步骤3 :添加数据 Web 控件,并将其绑定到 SqlDataSource

一旦配置了 SqlDataSource ,则它可以绑定到 GridView 或者 DetailsView 这样的 Web 数据控件。对此教程来说,我们在 GridView 中显示数据。从工具栏将 GridView 拖拽到页面上,并从 GridView 智能标记中的下拉列表将其绑定到 ProductsDataSource SqlDataSource 。

图10 :添加 GridView ,并将其绑定到 SqlDataSource 控件

一旦您从 GridView 智能标记中的下拉列表选择了 SqlDataSource 控件,Visual  Studio 将自动给数据源控件返回的数据的每一列,在 GridView 中的添加 BoundField 或 CheckBoxField 。由于 SqlDataSource 返回三个数据列 —— ProductID 、 ProductName 和 UnitPrice ,因此在 GridView 中有三个字段。

请花费几分钟时间配置 GridView 的三个 BoundField 。将 ProductName 字段的 HeaderText 属性更改为 "Product Name",将 UnitPrice 字段属性更改为 "Price"。此外,将 UnitPrice 字段设置为货币格式。在作出这些更改之后,GridView 的声明性标记应与下面类似:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID"
            InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="Product Name"
            SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="Price"
            SortExpression="UnitPrice" DataFormatString="{0:c}"
            HtmlEncode="False" />
    </Columns>
</asp:GridView>

通过浏览器访问此页面。如图 11 所示,GridView 将列出每个产品的ProductID 、ProductName 和 UnitPrice 值。

图11 :GridView 显示了每个产品的 ProductID 、ProductName 和 UnitPrice 值

访问页面时,GridView 将调用其数据源控件的Select () 方法。在使用 ObjectDataSource 控件时,它调用 ProductsBLL  类的 GetProducts () 方法。但是,通过 SqlDataSource ,Select () 方法将建立一个连接到特定数据库,并执行 SelectCommand (本例中为 SELECT [ProductID] 、 [ProductName] 和 [UnitPrice] FROM [Products] )。SqlDataSource 返回查询结果,随后 GridView 将枚举这些值,为每个返回的数据库记录在 GridView 中创建一行。

内置 Web 数据控件功能和 SqlDataSource 控件

一般情况下,Web 数据 控件有其特有的功能 —— 分页、排序、编辑、删除和插入等,这些并不依赖于所使用的数据源控件。也就是说,不管 GridView 是否绑定到ObjectDataSource 或者 SqlDataSource ,它均可使用其内置的分页、排序、编辑、删除和插入等功能。但是,某些 Web 数据控件的功能对使用的数据源控件或者数据源控件的配置敏感。

例如,在“大量数据的有效分页” 教程中,我们探讨了 Web 数据控件的分页逻辑自身如何从基础数据源返回所有记录,然后,仅在每个页面上显示适当记录的子集,列出当前页索引和每页显示的记录数。此模型在分页大量结果集时非常有效。幸运的是,ObjectDataSource 可配置为支持自定义分页,它仅返回要显示记录的精确子集。但是,SqlDataSource 控件缺少支持自定义分页的属性。

默认情况下,SqlDataSource 返回的数据可通过 GridView 进行分页或者排序。要演示此功能,请在 Querying.aspx 的 GridView 的智能标记中选中 Enable Paging 和 Enable Sorting 选项,确定它们能够正常工作。

因为 SqlDataSource 通过 数据库数据检索返回一个弱类型 DataSet ,因此分页和排序功能可正常工作。查询返回的总记录数是完成分页功能的一个重要方面,可从 DataSet 确定。此外,DataSet 的结果可通过 DataView 进行排序。GridView 请求分页数据或排序数据时,SqlDataSource 可自动使用这些功能。

SqlDataSource 可通过将 DataSourceMode 属性 从 DataSet (默认)更改为DataReader 配置来返回 DataReader ,而不是 DataSet 。在将 SqlDataSource 的结果传递给希望使用 DataReader 的代码时,可能更倾向于使用 DataReader 。此外,由于 DataReader 是比 DataSet 简单得多的对象,它们可提供更好的性能。如果您做了此更改,但是由于 SqlDataSource 无法确定查询返回的记录数,Web 控件 仍然无法进行排序或分页操作,同样,DataReader 也无法排序返回的数据。

步骤4 :使用定制 SQL 语句或者存储过程

配置 SqlDataSource 控件时,您可通过两种方式之一(例如定制 SQL 语句或者存储过程)来指定返回数据查询,或者作为已有表或视图来指定返回数据的查询。在步骤 2 中,我们探讨了如何从 Products 表中选择列。下面,我们探讨一下如何使用定制 SQL 语句。

给Querying.aspx 页面添加另外一个 GridView 控件,选择从智能标记的下拉列表创建新数据源。接下来,显示即将从数据库中提取的数据 —— 这将创建一个新 SqlDataSource 控件。将控件命名为 ProductsWithCategoryInfoDataSource 。

图12 :新建一个名为 ProductsWithCategoryInfoDataSource 的SqlDataSource 控件。

下一个屏幕要求我们指定数据库。重复图7 中的操作,从下拉列表选择NORTHWINDConnectionString ,单击 Next (下一步)。在 “ 配置 Select 语句 ” 屏幕上,选择 “指定定制 SQL 语句或者存储过程”选项,单击 Next (下一步)。计算机将显示“定义定制语句或存储程序”屏幕,此屏幕提供了 SELECT 、 UPDATE 、 INSERT 和 DELETE 选项卡。在每个选项卡中,您可以在文本框中输入定制 SQL 语句,或者从下拉列表选择存储过程。在本教程中,我们将探讨如何输入定制 SQL 语句;下一个教程将包含一个使用存储程序的示例。

图13 :输入定制 SQL 语句或者选取存储过程

定制SQL 语句可通过手动输入文本框的形式输入,或者单击 Query Builder 按钮进行图形化构建。在Query Builder 或者文本框中,选择下列查询从 Products 表返回ProductID 和ProductName ,使用 JOIN 从 Categories 表检索产品的CategoryName :

SELECT Products.ProductID, Products.ProductName, Categories.CategoryName FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID

图14 :您可以使用查询生成器图形化构建查询

在指定查询之后,单击 Next ,进入 "Test Query" 页面。单击 Finish 完成 SqlDataSource 向导。

完成向导之后,GridView 将被添加三个BoundField ,用来显示查询结果中的 ProductID 、 ProductName 和 CategoryName 列,生成的声明性标记如下所示:

<asp:GridView ID="GridView2" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ProductsWithCategoryInfoDataSource"
    EnableViewState="False">
    <Columns>
        <asp:BoundField DataField="ProductID" HeaderText="ProductID"
            InsertVisible="False" ReadOnly="True" SortExpression="ProductID" />
        <asp:BoundField DataField="ProductName" HeaderText="ProductName"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
            SortExpression="CategoryName" />
    </Columns>
</asp:GridView>
<asp:SqlDataSource ID="ProductsWithCategoryInfoDataSource" runat="server"
    ConnectionString="<%$ ConnectionStrings:NORTHWNDConnectionString %>"
    SelectCommand="
        SELECT Products.ProductID, Products.ProductName, Categories.CategoryName
        FROM Categories
        INNER JOIN Products ON Categories.CategoryID = Products.CategoryID">
</asp:SqlDataSource>

图15 :GridView 显示每个产品的ID 、名称和相关类别名称

小结

在本教程中,我们了解了如何使用 SqlDataSource 控件查询和显示数据。和 ObjectDataSource 一样,SqlDataSource 充当代理角色,提供访问数据的声明性方法。其属性指定了要连接的数据库和执行 SQL SELECT 查询;他们可以通过 Properties 窗口指定,或者使用 Configure DataSource 向导指定。

本教程所讨论的 SELECT 查询示例从指定的查询返回了所有的记录。SqlDataSource 控件可包含一个 WHERE 子句,此子句的参数值可通过编程分配 , 或者从指定的源提取。我们将在下一篇教程中探讨如何创建和使用带参数的查询!

快乐编程!

 

下一篇教程