使用 SqlDataSource 控件查询数据 (VB)

作者 :Scott Mitchell

下载 PDF

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

简介

到目前为止,我们研究的所有教程都使用了分层体系结构,该体系结构由表示层、业务逻辑层和数据访问层组成。 数据访问层 (DAL) 是在创建 数据访问层) 的第一个 教程和第二个 (创建业务逻辑层) 中创建数据访问层 (业务逻辑层 。 从 使用 ObjectDataSource 显示数据 教程开始,我们了解了如何使用 ASP.NET 2.0 秒的新 ObjectDataSource 控件以声明方式与表示层中的体系结构进行交互。

虽然到目前为止,所有教程都使用体系结构来处理数据,但也可以绕过体系结构,直接从 ASP.NET 页访问、插入、更新和删除数据库数据。 这样做会将特定的数据库查询和业务逻辑直接置于网页中。 对于足够大或复杂的应用程序,设计、实现和使用分层体系结构对于应用程序的成功、可更新性和可维护性至关重要。 但是,在创建极其简单的一次性应用程序时,可能不需要开发可靠的体系结构。

ASP.NET 2.0 提供五个内置数据源控件 SqlDataSourceAccessDataSourceObjectDataSourceXmlDataSourceSiteMapDataSource。 SqlDataSource 可用于直接从关系数据库(包括 Microsoft SQL Server、Microsoft Access、Oracle、MySQL 等)访问和修改数据。 在本教程和接下来的三个教程中,我们将了解如何使用 SqlDataSource 控件,探索如何查询和筛选数据库数据,以及如何使用 SqlDataSource 插入、更新和删除数据。

ASP.NET 2.0 包括五个 Built-In 数据源控件

图 1:ASP.NET 2.0 包括五个 Built-In 数据源控件

比较 ObjectDataSource 和 SqlDataSource

从概念上讲,ObjectDataSource 和 SqlDataSource 控件都只是数据的代理。 如 使用 ObjectDataSource 显示数据教程中所述,ObjectDataSource 具有指示提供数据的对象类型的属性,以及要调用以从基础对象类型中选择、插入、更新和删除数据的方法。 配置 ObjectDataSource 的属性后,GridView、DetailsView 或 DataList 等数据 Web 控件即可绑定到该控件,并使用 ObjectDataSource 的 Select()Insert()Delete()Update() 方法与基础体系结构进行交互。

SqlDataSource 提供相同的功能,但针对关系数据库而不是对象库运行。 使用 SqlDataSource 时,必须指定要执行的数据库连接字符串和临时 SQL 查询或存储过程,以插入、更新、删除和检索数据。 调用 SqlDataSource 的 Select()Insert()Update()Delete() 方法时,会连接到指定的数据库并发出相应的 SQL 查询。 如下图所示,这些方法执行连接到数据库、发出查询和返回结果等任务。

SqlDataSource 充当数据库的代理

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

注意

在本教程中,我们将重点介绍如何从数据库检索数据。 在 使用 SqlDataSource 控件插入、更新和删除数据 教程中,我们将了解如何将 SqlDataSource 配置为支持插入、更新和删除。

SqlDataSource 和 AccessDataSource 控件

除了 SqlDataSource 控件外,ASP.NET 2.0 还包括 AccessDataSource 控件。 这两种不同的控件导致许多刚接触 ASP.NET 2.0 的开发人员怀疑 AccessDataSource 控件设计为与专用于 Microsoft SQL Server的 SqlDataSource 控件一起与 Microsoft Access 一起使用。 虽然 AccessDataSource 专门用于 Microsoft Access,但 SqlDataSource 控件适用于可通过 .NET 访问 的任何 关系数据库。 这包括任何符合 OleDb 或 ODBC 的数据存储,例如 Microsoft SQL Server、Microsoft Access、Oracle、Informix、MySQL 和 PostgreSQL 等。

AccessDataSource 和 SqlDataSource 控件之间的唯一区别在于如何指定数据库连接信息。 AccessDataSource 控件只需要 Access 数据库文件的文件路径。 另一方面,SqlDataSource 需要完整的连接字符串。

步骤 1:创建 SqlDataSource 网页

在开始探索如何使用 SqlDataSource 控件直接处理数据库数据之前,让我们先花点时间在网站项目中创建本教程和后续三个页面所需的 ASP.NET 页面。 首先添加名为 SqlDataSource的新文件夹。 接下来,将以下 ASP.NET 页添加到该文件夹,确保将每个页面与 Site.master 母版页相关联:

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

为 SqlDataSource-Related 教程添加 ASP.NET 页面

图 3:为 SqlDataSource-Related 教程添加 ASP.NET 页面

与其他文件夹中一样, Default.aspx 文件夹中 SqlDataSource 会列出其部分的教程。 回想一下, SectionLevelTutorialListing.ascx 用户控件提供此功能。 因此,将此用户控件Default.aspx从解决方案资源管理器拖到页面设计视图中,将其添加到 。

将 SectionLevelTutorialListing.ascx 用户控件添加到 Default.aspx

图 4:将 SectionLevelTutorialListing.ascx 用户控件添加到 Default.aspx (单击 以查看全尺寸图像)

最后,将这四个页面作为条目添加到 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后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包含用于编辑、插入和删除教程的项目。

站点地图现在包括 SqlDataSource 教程的条目

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

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

首先打开 文件夹中的页面 Querying.aspxSqlDataSource 然后切换到“设计”视图。 将 SqlDataSource 控件从工具箱拖到Designer并将其设置为 IDProductsDataSource。 与 ObjectDataSource 一样,SqlDataSource 不会生成任何呈现的输出,因此在设计图面上显示为灰色框。 若要配置 SqlDataSource,请单击 SqlDataSource 智能标记中的“配置数据源”链接。

单击 SqlDataSource 智能标记中的“配置数据Source Link

图 6:单击 SqlDataSource 智能标记中的“配置数据Source Link

这会显示 SqlDataSource 控件的“配置数据源”向导。 虽然向导的步骤与 ObjectDataSource 控件不同,但最终目标相同,目的是提供有关如何通过数据源检索、插入、更新和删除数据的详细信息。 对于 SqlDataSource,这需要指定要使用的基础数据库,并提供即席 SQL 语句或存储过程。

第一个向导步骤提示我们输入数据库。 下拉列表包括 Web 应用程序 App_Data 文件夹中的数据库,以及已添加到服务器资源管理器中“数据Connections”节点的数据库。 由于我们已将 文件夹中的数据库App_Data连接字符串NORTHWIND.MDF添加到项目文件Web.config,因此下拉列表包含对连接字符串NORTHWINDConnectionString的引用。 从下拉列表中选择此项,然后单击“下一步”。

从 Drop-Down 列表中选择 NORTHWINDConnectionString

图 7NORTHWINDConnectionString 从 Drop-Down 列表中选择

选择数据库后,向导会要求查询返回数据。 我们可以指定要返回的表或视图的列,也可以输入自定义 SQL 语句或指定存储过程。 可以通过“指定自定义 SQL 语句或存储过程”和“指定表或视图中的列”单选按钮在此选项之间切换。

注意

对于第一个示例,让我们使用“指定表或视图中的列”选项。 本教程稍后将返回到向导,并浏览“指定自定义 SQL 语句或存储过程”选项。

图 8 显示选中“指定表或视图中的列”单选按钮时,“配置 Select 语句”屏幕。 下拉列表包含 Northwind 数据库中的表和视图集,所选表或视图列显示在下面的复选框列表中。 对于此示例,让我们从Products表中返回 ProductIDProductNameUnitPrice 列。 如图 8 所示,在进行这些选择后,向导会显示生成的 SQL 语句 SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products]

从产品表返回数据

图 8:从 Products 表返回数据

将向导配置为从Products表中返回 ProductIDProductNameUnitPrice 列后,单击“下一步”按钮。 此最后一个屏幕提供了检查上一步中配置的查询结果的机会。 单击“测试查询”按钮将执行配置的 SELECT 语句,并在网格中显示结果。

单击“测试查询”按钮,查看 SELECT 查询

图 9:单击“测试查询”按钮以查看查询SELECT

若要完成向导,请单击“完成”。

与 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 指定要执行的即席 SQL 语句或存储过程以返回数据。

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

配置 SqlDataSource 后,可以将其绑定到数据 Web 控件,例如 GridView 或 DetailsView。 在本教程中,让我们在 GridView 中显示数据。 从“工具箱”中,将 GridView 拖到页面上,并通过从 GridView 智能标记中的下拉列表中选择数据源,将其 ProductsDataSource 绑定到 SqlDataSource。

添加 GridView 并将其绑定到 SqlDataSource 控件

图 10:添加 GridView 并将其绑定到 SqlDataSource 控件 (单击以查看全尺寸图像)

从 GridView 智能标记的下拉列表中选择 SqlDataSource 控件后,Visual Studio 会自动为数据源控件返回的每个列添加 BoundField 或 CheckBoxField 到 GridView。 由于 SqlDataSource 返回三个数据库列 ProductIDProductNameUnitPrice GridView 中有三个字段。

花点时间配置 GridView 的三个 BoundField。 将 ProductName 字段 属性 HeaderText 更改为“产品名称”,将 UnitPrice 字段更改为“价格”。 此外,将 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 列出了每个产品的 ProductIDProductNameUnitPrice 值。

GridView 显示每个产品的 ProductID、ProductName 和 UnitPrice 值

图 11:GridView 显示每个产品的 ProductIDProductNameUnitPrice 值 (单击以查看全尺寸图像)

访问页面时,GridView 会调用其数据源控件 的 Select() 方法。 当我们使用 ObjectDataSource 控件时,这调用了 ProductsBLL 类 s GetProducts() 方法。 但是,对于 SqlDataSource, Select() 方法会建立与指定数据库的连接,并发出 SelectCommand (SELECT [ProductID], [ProductName], [UnitPrice] FROM [Products],在此示例中) 。 SqlDataSource 返回其结果,然后由 GridView 枚举,在 GridView 中为返回的每个数据库记录创建一行。

Built-In Data Web 控件功能和 SqlDataSource 控件

通常,数据 Web 控件固有的功能分页、排序、编辑、删除、插入等特定于数据 Web 控件,不依赖于所使用的数据源控件。 也就是说,无论 GridView 是绑定到 ObjectDataSource 还是 SqlDataSource,GridView 都可以利用其内置的分页、排序、编辑和删除功能。 但是,某些数据 Web 控件功能对正在使用的数据源控件或数据源控件的配置敏感。

例如,在 “通过大量数据进行高效分页 ”教程中,我们讨论了默认情况下,数据 Web 控件的分页逻辑如何从基础数据源中以朴素方式返回 所有 记录,然后根据当前页索引和每页要显示的记录数仅显示适当的记录子集。 在对足够大的结果集进行分页时,此模型效率非常低。 幸运的是,ObjectDataSource 可以配置为支持自定义分页,这仅返回要显示的记录的精确子集。 但是,SqlDataSource 控件缺少用于实现自定义分页的属性。

分页和排序的另一个微妙之处是 SqlDataSource。 默认情况下,可以从 SqlDataSource 返回的数据通过 GridView 进行分页或排序。 为了演示这一点,检查中的“在 GridView 智能标记Querying.aspx中启用分页”和“启用排序”选项,并验证这是否按预期工作。

排序和分页之所以有效,是因为 SqlDataSource 将数据库数据检索到松散类型的数据集中。 可从 DataSet 中确定查询返回的记录总数,这是实现分页的关键方面。 此外,可以通过 DataView 对数据集的结果进行排序。 当 GridView 请求分页或排序的数据时,SqlDataSource 会自动使用这些功能。

可以通过将 SqlDataSource 的属性 (从DataSet默认 DataReader) 更改为 DataSourceMode ,将其配置为返回 DataReader 而不是 DataSet。 在将 SqlDataSource 结果传递给需要 DataReader 的现有代码时,可能首选使用 DataReader。 此外,由于 DataReader 是比 DataSet 简单得多的对象,因此它们的性能更好。 但是,如果进行此更改,数据 Web 控件既不能排序也不能分页,因为 SqlDataSource 无法确定查询返回的记录数,DataReader 也不会提供对返回的数据进行排序的任何技术。

步骤 4:使用自定义 SQL 语句或存储过程

配置 SqlDataSource 控件时,可以使用两种方法之一将用于返回数据的查询指定为自定义 SQL 语句或存储过程,或者指定为现有表或视图中的列。 在步骤 2 中,我们检查了如何从 Products 表中选择列。 让我们看看如何使用自定义 SQL 语句。

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

新建名为 ProductsWithCategoryInfoDataSource 的 SqlDataSource 控件

图 12:创建名为 的新 SqlDataSource 控件 ProductsWithCategoryInfoDataSource

下一个屏幕要求我们指定数据库。 正如我们在图 7 中所做的那样,从下拉列表中选择 NORTHWINDConnectionString ,然后单击“下一步”。 在“配置 Select 语句”屏幕中,选择“指定自定义 SQL 语句或存储过程”单选按钮,然后单击“下一步”。 此时会显示“定义自定义语句或存储过程”屏幕,其中提供标记为 SELECT、UPDATE、INSERT 和 DELETE 的选项卡。 在每个选项卡中,可以在文本框中输入自定义 SQL 语句,或从下拉列表中选择存储过程。 在本教程中,我们将了解如何输入自定义 SQL 语句;下一教程包含一个使用存储过程的示例。

输入自定义 SQL 语句或选取存储过程

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

自定义 SQL 语句可以手动输入到文本框中,也可以通过单击“查询生成器”按钮以图形方式构造。 在“查询生成器”或文本框中,使用以下查询从表中返回 ProductIDProductName 字段,并使用 JOINCategories表中检索产品CategoryNameProducts

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

可以使用查询生成器以图形方式构造查询

图 14:可以使用查询生成器以图形方式构造查询

指定查询后,单击“下一步”转到“测试查询”屏幕。 单击“完成”以完成 SqlDataSource 向导。

完成向导后,GridView 将添加三个 BoundField,显示 ProductID从查询返回的 、 ProductNameCategoryName 列,并生成以下声明性标记:

<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>

GridView 显示每个产品的 ID、名称和关联的类别名称

图 15:GridView 显示每个产品的 ID、名称和关联的类别名称 (单击以查看全尺寸图像)

总结

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

SELECT我们在本教程中检查的查询示例返回了指定查询中的所有记录。 但是,SqlDataSource 控件可以包含一个 WHERE 子句,其值以编程方式分配或从指定源自动拉取。 下一教程将介绍如何创建和使用参数化查询!

编程愉快!

深入阅读

有关本教程中讨论的主题的详细信息,请参阅以下资源:

关于作者

Scott Mitchell 是七本 ASP/ASP.NET 书籍的作者, 4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可以在 上联系 mitchell@4GuysFromRolla.com他, 也可以通过他的博客联系到他,该博客可在 http://ScottOnWriting.NET中找到。

特别感谢

本教程系列由许多有用的审阅者查看。 本教程的主要审阅者是 Susan Connery、Bernadette Leigh 和 David Suru。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处放置一行 mitchell@4GuysFromRolla.com。