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

作者 :斯科特·米切尔

下载 PDF

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

介绍

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

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

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

ASP.NET 2.0 包括五个内置数据源控件

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

比较 ObjectDataSource 和 SqlDataSource

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

SqlDataSource 提供相同的功能,但针对关系数据库而不是对象库进行操作。 使用 SqlDataSource,必须指定数据库连接字符串和临时 SQL 查询或存储过程来执行以插入、更新、删除和检索数据。 调用 SqlDataSource s 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 页面,本教程和接下来的三个页面。 首先添加名为 <a0/a0> 的新文件夹。 接下来,将以下 ASP.NET 页添加到该文件夹,确保将每个页面与 Site.master 母版页相关联:

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

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

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

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

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

图 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后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包括用于编辑、插入和删除教程的项目。

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

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

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

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

单击 SqlDataSource 智能标记中的“配置数据源链接”

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

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

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

从下拉列表中选择 NORTHWINDConnectionString

图 7NORTHWINDConnectionString 从下拉列表中选择

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

注意

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

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

从产品表返回数据

图 8:从 Products 表返回数据

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

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

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

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

与 ObjectDataSource 一样,SqlDataSource 向导只是将值分配给控件的属性,即 ConnectionString 属性和 SelectCommand 属性。 完成向导后,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 返回三个数据库列 ProductIDProductName并且 UnitPrice GridView 中有三个字段。

花点时间配置 GridView s 三个 BoundFields。 将 ProductName 字段属性 HeaderText 更改为产品名称,并将 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 列出了每个产品ProductIDProductName以及UnitPrice值。

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

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

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

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

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

例如,在 “有效分页到大量数据” 教程中,我们讨论了数据 Web 控件的分页逻辑如何天生地返回 基础数据源中的所有 记录,然后仅显示给定当前页索引的相应记录子集以及每页要显示的记录数。 当分页到足够大的结果集时,此模型效率很高。 幸运的是,可以将 ObjectDataSource 配置为支持自定义分页,该分页仅返回要显示的记录的精确子集。 但是,SqlDataSource 控件缺少实现自定义分页的属性。

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

排序和分页的工作原理是 SqlDataSource 将数据库数据检索到松散类型的数据集中。 可以从 DataSet 确定查询返回的记录总数,这是实现分页的一个重要方面。 此外,数据集的结果也可以通过 DataView 进行排序。 当 GridView 请求分页或排序数据时,SqlDataSource 会自动使用这些功能。

可以将 SqlDataSource 配置为通过将 DataReader 的属性DataSet (默认值) 更改为DataReaderDataSourceMode返回 DataReader 而不是 DataSet。 在将 SqlDataSource 结果传递给需要 DataReader 的现有代码时,使用 DataReader 可能首选 DataReader。 此外,由于 DataReaders 比数据集要简单得多,因此它们可提供更好的性能。 但是,如果进行此更改,则数据 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 语句可以手动输入到文本框中,也可以通过单击“查询生成器”按钮以图形方式构造。 在查询生成器或文本框中,使用以下查询从表中返回ProductID表的字段和ProductName字段,该查询Products使用从JOIN表中检索产品CategoryNameCategories

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

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

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

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

完成向导后,GridView 将添加三个 BoundFields,其中显示了ProductIDProductName从查询返回的列和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>

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

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

总结

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

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

快乐编程!

深入阅读

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

关于作者

斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0。 他可以通过他的博客联系到mitchell@4GuysFromRolla.com他,可以在该博客中找到http://ScottOnWriting.NET

特别感谢

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