创建数据访问层

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

该教程从头开始使用 Typed DataSet(强类型 DataSet)创建数据访问层 (DAL),以访问数据库中的信息。

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

简介

作为 web 开发人员,我们的工作总是在和数据打交道。我们创建数据库来存储数据, 创建代码来检索并修改数据,并创建 Web 页面来收集和汇总数据。这是探讨在 ASP.NET 2.0 中 实现这些常用类型的技巧的系列教程中的首篇教程。 我们从创建一个软件架构开始,包括使用 Typed DataSet 的数据访问层 (DAL)、实现自定义业务规则的业务逻辑层 (BLL) 和共享同一页面布局的 ASP.NET 页面组成的表示层。一旦奠定了这个后端基础,我们接下来会转向报表,说明如何显示、汇总、收集和验证来自 Web 应用程序的数据。这些教程力求简明,使用大量屏幕截图逐步教您直观地了解整个流程。每个教程都提供 C# 和 Visual Basic 版本,并且可以下载所使用的全部代码。(这篇教程内容非常冗长,但接下来会分几大部分进行介绍,使人更容易理解和消化。)

针对这些教程,我们将使用放在 App_Data 目录下 Northwind 数据库的 Microsoft SQL Server 2005 Express Edition版。除数据库文件外,App_Data文件夹也包含创建该数据库的 SQL 脚本,以满足您想使用不同数据库版本的需求。如果愿意,这些脚本也可以直接从 Microsoft 下载如果您使用的是 Northwind 数据库的不同 SQL Server 版本,需要更新该应用程序的Web.config文件中的NORTHWNDConnectionString设置。这个 Web 应用程序是使用 Visual Studio 2005 Professional Edition 创建的基于文件系统的 Web 站点项目。不过,所有的这些教程同样适用于 Visual Studio 2005 免费版,即 Visual Web Developer

该教程从头开始,先创建数据访问层(DAL),然后在第二篇教程中创建业务逻辑层(BLL)并在第三篇教程中进行 页面布局和导航。随后的教程以前三篇教程为基础。在这本教程中我们有很多内容要学习,现在就让我们打开Visual Studio 开始吧!

步骤 1:创建一个 Web 项目并连接到数据库

在创建我们的数据访问层 (DAL) 之前,我们首先需要创建一个网站并安装我们的数据库。开始创建一个新的基于文件系统的 ASP.NET 网站:从 File 菜单选择 New Web Site,出现 New Web Site 对话框。选择 ASP.NET Web Site 模板,将 Location 下拉列表设置成 File System,然后为该网站选择一个文件夹,并将语言设置成 Visual Basic。

图1: 创建一个基于文件系统的新网站

这将创建一个具有Default.aspx页面、App_Data文件夹和Web.config文件的新网站。

创建好了网站,下一步是在 Visual Studio 的 Server Explorer 中添加对该数据库的引用。通过在 Server Explorer 中添加数据库,您可以添加来自 Visual Studio 的表、存储过程、视图等。您还可以手动或通过 Query Builder 直观地查看表数据或进行查询。而且,当我们为 DAL 创建 Typed DataSet 时,我们需要将 Visual Studio 指向需要建立 Typed DataSet 的数据库。当我们能够及时在那个点上提供这种连接信息时,Visual Studio 自动填充己在 Server Explorer注册过的数据库的下拉列表。

将 Northwind 数据库添加到 Server Explorer 的步骤取决于您是否愿意使用App_Data文件夹中的 SQL Server 2005 Express Edition 数据库,或者是否有您想使用的 Microsoft SQL Server 2000 或 2005 数据库服务器安装程序。

使用App_Data文件夹中的数据库

如果您没有SQL Server 2000 或2005 数据库服务器可连接,或者您只想 避免将该数据库添加到数据库服务器的麻烦,可以使用位于已下载 网站的App_Data文件夹(NORTHWND.MDF) 的 Northwind 数据库的SQL Server 2005 Express Edition 版本。

位于App_Data文件夹中的数据库被自动添加到 Server Explorer。假如您安装了SQL Server 2005 Express Edition, 在 Server Explorer 应该看到一个名为 NORTHWND.MDF 的节点, 可以拓展并探究其表、视图、存储过程等(见图2)。

App_Data文件夹也可以存放Microsoft Access .mdb文件。 同它们的 SQL Server 版本的数据库一样,这类文件将被自动添加到 Server Explorer。如果您不想使用任何 SQL Server 的数据库,您可以 下载Northwind数据库文件的Microsoft Access 版本并加入App_Data目录。不过要记住,Access 数据库的特性不如 SQL Server丰富,且并不是为在网站环境下使用而设计的。另外, 35 以后的教程将用到某些不被 Access 支持的数据库级特性。

连接到 Microsoft SQL Server 2000 or 2005 数据库服务器中的数据库

同样,您可能要连接到安装在数据库服务器上的Northwind数据库。如果数据库服务器还没有安装Northwind数据库,您必须先运行该教程下载文件中的安装脚本或直接从Microsoft网站下载 Northwind 的 SQL Server 2000 版本和安装脚本, 将其添加到数据库服务器。

一旦安装了该数据库,转到Visual Studio的Server Explorer,右键单击Data Connections节点并选择Add Connection。如果没有找到Server Explorer,转入View / Server Explorer或选择Ctrl+Alt+S。这时将出现Add Connection对话框,在这里可以指定要连接的服务器,认证信息和数据库名称。一旦成功配置了数据库连接信息,单击OK 按钮,该数据库将被作为一个节点添加到 Data Connections 节点下面。您可以展开该数据库节点以探究其表、视图、存储过程等。

图2: 在您的数据库服务器的 Northwind 数据库添加一个连接

步骤 2:创建数据访问层

在处理数据时,有个选项是将数据的特定逻辑直接内嵌到表示层(Web 应用程序中,ASP.NET 页面组成表示层)。这可以通过在 ASP.NET 页面的代码部分编写 ADO.NET 代码,或者在标记符部分使用 SqlDataSource 控件来完成。无论采取哪种形式,该方法都让数据访问逻辑与表示层紧密结合。不过,建议将数据访问与表示层隔离开来。这个分离层被称作数据访问层 (DAL),通常作为一个单独的类库项目来实现。这种分层体系结构的优势得到了很好的论述,我们在该系列教程中也采用了此法。

有关基础数据源的所有代码,如创建到数据库的连接,发出SELECT, INSERT,UPDATE, and DELETE命令等,都应位于 DAL。表示层不应包含对这些数据访问代码的任何引用,而是通过调用 DAL 来实现所有的数据访问请求。数据访问层通常包含访问基础数据库数据的方法。例如,Northwind 数据库提供ProductsandCategories表,记录要销售的产品及其他们所属的类别。我们的 DAL 提供如下方法:

  • GetCategories(),:返回所有类别的信息
  • GetProducts():返回所有产品的信息
  • GetProductsByCategoryID(categoryID):返回属于某一指定类别的所有产品
  • GetProductByProductID(productID):返回某一产品的信息

调用时,这些方法将连接到数据库,进行适当的查询,并返回查询结果。重要的是返回这些结果的方式。这些方法可以简单返回一个由数据库查询填充的 DataSet 或 DataReader,但理想的是应使用强类型的对象来返回这些结果。强类型对象指的是编译时对其 schema 进行严格定义的对象。相反,弱类型的对象指的是只有在运行时才知道其 schema 的对象。

例如,DataReader 和 DataSet(默认)是弱类型对象,因为它们的 schema 是由用来填充它们的数据库查询返回的列来定义的。要访问弱类型 DataTable 中的某列,需要使用如下语法:DataTable.Rows(index)("columnName"). 我们需要使用字符串或序号索引访问列名这一点就显示了该例中 DataTable 的弱类型特性。另一方面,强类型的 DataTable 有各自作为属性实现的列,生成如下代码:DataTable.Rows(index).columnName.

要返回强类型对象,开发人员可以创建他们自己的自定义业务对象或使用 Typed DataSet。一个业务对象由开发人员实现成一个类,该类的属性通常反映出该业务对象表示的基础数据库表的列。Typed DataSet 是由 Visual Studio 基于数据库 schema 为您生成的一个类,其成员都是强类型的。Typed DataSet 本身包括拓展了 ADO.NET DataSet、DataTable 和 DataRow 类的类。除强类型 DataTable 外,Typed DataSet 现在还包括 TableAdapter,该类具有填充 DataSet 的 DataTable 以及将 DataTable 中所作修改传回数据库的方法。

注意: 有关使用 Typed DataSet 与自定义业务对象的优劣比较的更多信息,请参见设计数据层组件并在层间传递数据

我们对这些教程的体系结构使用强类型的 DataSet。图 3 说明了使用 Typed DataSet 的应用程序不同层间的工作流程。

图3: 选择添加一个新的 DataSet 到您的项目

创建一个 Typed DataSet 和 Table Adapter

要创建我们的 DAL,要先将一个 Typed DataSet 添加到我们的项目。为此,右键单击 Solution Explorer 中的项目节点,并选择 Add a New Item。从模板列表中选择 DataSet 选项,并将其命名为Northwind.xsd

图4: 选择添加一个新的 DataSet 到您的项目

单击 Add 后,出现提示添加 DataSet 到App_Code 文件夹,选择 Yes。接着出现 Typed DataSet 设计器并将启动 TableAdapter Configuration Wizard,允许您将您的第一个 TableAdapter 添加到 Typed DataSet。

Typed DataSet 充当一个强类型的数据集;它由强类型的 DataTable 实例组成,每个实例依次由强类型的 DataRow 实例组成。我们将为该教程系列所需的每个基础数据库表创建一个强类型的 DataTable。.我们开始为 Products 表创建 DataTable。

要记住,强类型的 DataTable 不包含有关如何从其基础数据库表访问数据的任何信息。为了检索数据以填充 DataTable,我们使用一个 TableAdapter 类,作为我们的数据访问层。对于我们的Products数据表,TableAdapter 将包含GetProducts(),GetProductByCategoryID(categoryID)等方法,我们将从表示层调用它们。DataTable 的作用是充当用来在层间传送数据的强类型对象。

TableAdapter Configuration Wizard 从提示您选择要操作的数据库开始。下拉列表显示出 Server Explorer 中的数据库。如果您没有把 Northwind 数据库添加到 Server Explorer,此时单击 New Connection 按钮进行该操作。

图5: 从下拉列表中选择 Northwind 数据库

选择了数据库并单击 Next 后, 将会问您是否希望在Web.config文件中保存连接字符串。保存了连接字符串,就避免了将连接字符串写在 TableAdapter 类的代码中。这样一旦以后连接字符串信息改变,要做的工作也变得简单。如果选择将连接字符串保存到放在<connectionStrings>区域的配置文件,以后可以通过 IIS GUI Admin Tool 内的新 ASP.NET 2.0 Property Page 选择加密以改进安全性或修改。这样更适合管理员工作。

图6: 保存连接字符串到Web.config

接下来,我们需要为第一个强类型的 DataTable 定义 schema,并为我们的 TableAdapter 提供填充强类型的 DataSet 时所用到的第一个方法。通过创建一个查询,可同时完成这两个步骤,这个查询能够返回我们希望映射我们的 DataTable 中的数据表的列。在向导结束时,我们将为该查询提供一个方法名称。完成后,就可以从我们的表示层调用该方法。此法将执行所定义的查询并填充强类型的 DataTable。

要开始定义 SQL 查询,就必须先说明希望 TableAdapter 进行查询的方式。我们可以使用一个 ad-hoc SQL 语句,创建一个新的存储过程,或使用现有的存储过程。对于本系列教程,我们将使用 ad-hoc SQL 语句。有关使用存储过程的例子,请参见Brian Noyes的文章: 使用 Visual Studio 2005 DataSet Designer 构建一个数据访问层。

图7: 使用 ad-hoc SQL 语句查询数据

此时,我们可以手动输入 SQL 查询。在 TableAdapter 创建第一个方法时,您通常希望查询返回需要在相应 DataTable 中存放的那些列。这可以通过创建返回来自Products表的所有列和行的查询实现:

图8: 在文本框输入 SQL 查询

也可以使用 Query Builder 用图像构建查询,如图 9 所示。

图9: 通过 Query Editor 用图像创建查询

创建查询之后,要在转到下一屏幕之前,单击 Advanced Options 按钮。在 Web Site 项目中,“Generate Insert, Update, and Delete statements”是默认选择的唯一高级选项;如果从 Class Library 或 Windows Project 运行该向导,“Use optimistic concurrency(使用优化并发)”选项将也被选中。现在暂不勾选该选项。我们将在以后的教程中详细介绍优化并发。

图10: 只选择“Generate Insert, Update, and Delete statements”选项

核实了高级选项后,单击 Next 进入最后一个屏幕。这时会询问我们选择那些方法添加到 TableAdapter。填充数据的模式有两种:

  • Fill a DataTable – 通过这种途径创建的方法将 DataTable作为一个参数,并根据查询结果对其进行填充。例如,ADO.NET DataAdapter 类使用其Fill()方法实现该模式。
  • Return a DataTable – 通过这种途径创建的方法为您创建并填充 DataTable,并将 DataTable 作为方法的返回值。

您可以在 TableAdapter 实现这两种模式中的一种或两种。也可以重命名此处所提供的方法。即使我们在整个教程中只使用第二种模式,我们也可以同时选中两个复选框。并且将更通用的GetData 法重命名为 GetProducts.

如果选中最后一个复选框 "GenerateDBDirectMethods",会为 TableAdapter 创建Insert(),Update(),和Delete()方法。如果没有选中该选项,所有的更新则需要通过 TableAdapter 唯一的Update()方法进行,该方法接受 Typed DataSet、DataTable、单个 DataRow 或 DataRow 数组。(如果没有选中图 9 高级选项中的"Generate Insert, Update, and Delete statements" 选项,该复选框的设置则不起作用。)在这里,我们勾选这个复选框。

图11: 将方法名称GetData 改为GetProducts

单击 Finish 结束向导。向导关闭后,返回到显示我们刚创建的 DataTable 的 DataSet 设计器。可以看到Products数据表中各列的列表 (ProductID,ProductName数据表中各列的列表),以及ProductsTableAdapter (Fill()的方法GetProducts())。

图12:Products DataTableProductsTableAdapter已被添加到 Typed DataSet

这里,我们拥有一个带有单个 DataTable (Northwind.Products) 的Typed DataSet,还有一个提供GetProducts()方法的强类型 DataAdapter 类(NorthwindTableAdapters.ProductsTableAdapter) 。这些对象可用来通过类似以下代码访问所有产品的列表:

 

Dim productsAdapter As New NorthwindTableAdapters.ProductsTableAdapter()
Dim products as Northwind.ProductsDataTable
products = productsAdapter.GetProducts()
For Each productRow As Northwind.ProductsRow In products
    Response.Write("Product: " & productRow.ProductName & "<br />")
Next

该代码不要求我们去编写任何针对数据访问的代码。我们不必生成任何 ADO.NET 类的实例,不必指定任何连接字符串、SQL 查询或存储过程。TableAdapter 会为我们提供底层的数据访问代码。

本示例中所使用的每个对象都是强类型的,允许 Visual Studio 提供 IntelliSense (智能感知)和编译时类型检查。而且,最好的是,TableAdapter 返回的 DataTable 可以绑定到 ASP.NET Web 数据控件,如 GridView、DetailsView、DropDownList、CheckBoxList 和其它。下面举例说明如何在 Page_Load事件处理程序仅用三行代码就将GetProducts() 方法返回的 DataTable 绑定到 GridView。

AllProducts.aspx

<%@ Page Language="VB" AutoEventWireup="true" CodeFile="AllProducts.aspx.vb"
    Inherits="AllProducts" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>View All Products in a GridView</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <h1>
            All Products</h1>
        <p>
            <asp:GridView ID="GridView1" runat="server"
             CssClass="DataWebControlStyle">
               <HeaderStyle CssClass="HeaderStyle" />
               <AlternatingRowStyle CssClass="AlternatingRowStyle" />
            </asp:GridView>
             </p>
    </div>
    </form>
</body>
</html>

AllProducts.aspx.vb

Imports NorthwindTableAdapters
Partial Class AllProducts
    Inherits System.Web.UI.Page
    Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles Me.Load
        Dim productsAdapter As New ProductsTableAdapter
        GridView1.DataSource = productsAdapter.GetProducts()
        GridView1.DataBind()
    End Sub
End Class

图13: 显示在 GridView 中的产品列表

尽管本例还需要我们在 ASP.NET 页面的Page_Load事件处理程序中编写三行代码,不过在以后的教程中我们将详细介绍如何使用 ObjectDataSource,用声明的方式获取 DAL 数据。使用 ObjectDataSource 我们不必编写代码也可以进行分页和排序!





上一页 | 1 | 2 | 3 | 下一页