ASP.NET2.0数据操作之创建数据访问层(4)

第五步:完成数据访问层

  注意,ProductsTableAdapters类从Products表中返回的 是CategoryID和SupplierID的值,但并不包括Categories表 的CategoryName字段和Suppliers表的CompanyName字段,尽管当 我们显示产品信息时,这些很可能是我们想要显示的字段。我们可以扩充TableAdapter的起始方 法GetProducts()来包含CategoryName和CompanyName字段的值, 这方法进而会更新强类型的DataTable来包括这些新的字段。

  但这会造成一个问题,因为TableAdapter的插入,更新,删除数据的方法是基于这个起始方法的,幸运的是, 自动生成的插入,更新,删除方法并不会受SELECT子句中的子查询的影响。如果我们注意把 对Categories和Suppliers的查询添加成子查询,而不是用JOIN语 句的话,我们可以避免重做这些修改数据的方法。在ProductsTableAdapter中的GetProducts()方法上按右鼠标,选择“配置”,然后,把SELECT子句改成:

SQL
1

            2

            3

            4

            5

            6

            7

            
SELECT     ProductID, ProductName, SupplierID, CategoryID,

            QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued,

            (SELECT CategoryName FROM Categories

            WHERE Categories.CategoryID = Products.CategoryID) as CategoryName,

            (SELECT CompanyName FROM Suppliers

            WHERE Suppliers.SupplierID = Products.SupplierID) as SupplierName

            FROM         Products

            


ASP.NET2.0数据操作之创建数据访问层(4)
图29: 更新GetProducts()方法的SELECT语句

  在更新GetProducts()方法使用这个新查询语句之后,对应的DataTable将包含2个新字段,CategoryName和SupplierName。

ASP.NET2.0数据操作之创建数据访问层(4)
图30: Products DataTable多了2个新字段

  花点时间把GetProductsByCategoryID(categoryID)方法中的SELECT 子句也更新一下。

  如果你使用JOIN句法更新GetProducts()中的SELECT语句的话 ,DataSet设计器不能使用DB直接模式自动生成插入,更新,以及删除数据库记录的方法。你必须手工生成这 些方法,就象本教程早先时候我们对InsertProduct方法的做法一样。此外,你必须手工提供 InsertCommand,UpdateCommand和DeleteCommand属性值,假如你 想使用批更新模式的话。

  添加其他的TableAdapter

  到目前为止,我们只讨论了针对单个数据表的单个TableAdapter。但是,Northwind数据库里含有我们需要在 我们的web应用中使用的几个相关的表。一个强类型的DataSet可以包含多个相关的DataTable。因此,为了完 成我们的DAL,我们需要为这些我们将来要用到的数据表添加相应的DataTable。步骤如下,打开 DataSet设计 器,在设计器上按右鼠标,选择“添加/TableAdapter”。这会生成一个新的DataTable和TableAdapter,然后我 们早先讨论过的配置向导会指引你完成配置。

  花上几分钟,创建对应于下列查询的TableAdapter及其方法。注意,ProductsTableAdapter的查询中包含了用以获取每个产品的分类和供应商名字的子查询。另外,如果你是随着教程在做的话,你已经添加过ProductsTableAdapter类 的GetProducts()和GetProductsByCategoryID(categoryID)方法了。

  • ProductsTableAdapter
    • GetProducts:

      SELECT ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued , (SELECT CategoryName FROM
      Categories WHERE Categories.CategoryID =
      Products.ProductID) as CategoryName, (SELECT CompanyName
      FROM Suppliers WHERE Suppliers.SupplierID =
      Products.SupplierID) as SupplierName
      FROM Products
    • GetProductsByCategoryID:

      SELECT ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued , (SELECT CategoryName FROM
      Categories WHERE Categories.CategoryID =
      Products.ProductID) as CategoryName,
      (SELECT CompanyName FROM Suppliers WHERE
      Suppliers.SupplierID = Products.SupplierID) as SupplierName
      FROM Products
      WHERE CategoryID = @CategoryID
    • GetProductsBySupplierID

      SELECT ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued ,
      (SELECT CategoryName FROM Categories WHERE
      Categories.CategoryID = Products.ProductID)
      as CategoryName, (SELECT CompanyName FROM Suppliers
      WHERE Suppliers.SupplierID = Products.SupplierID)
      as SupplierName
      FROM Products
      WHERE SupplierID = @SupplierID
    • GetProductByProductID

      SELECT ProductID, ProductName, SupplierID, CategoryID,
      QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder,
      ReorderLevel, Discontinued , (SELECT CategoryName
      FROM Categories WHERE Categories.CategoryID =
      Products.ProductID) as CategoryName,
      (SELECT CompanyName FROM Suppliers
      WHERE Suppliers.SupplierID = Products.SupplierID)
      as SupplierName
      FROM Products
      WHERE ProductID = @ProductID

  • CategoriesTableAdapter
    • GetCategories

      SELECT CategoryID, CategoryName, Description
      FROM Categories
    • GetCategoryByCategoryID

      SELECT CategoryID, CategoryName, Description
      FROM Categories
      WHERE CategoryID = @CategoryID

  • SuppliersTableAdapter
    • GetSuppliers

      SELECT SupplierID, CompanyName, Address, City,
      Country, Phone
      FROM Suppliers
    • GetSuppliersByCountry

      SELECT SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM Suppliers
      WHERE Country = @Country
    • GetSupplierBySupplierID

      SELECT SupplierID, CompanyName, Address,
      City, Country, Phone
      FROM Suppliers
      WHERE SupplierID = @SupplierID

  • EmployeesTableAdapter
    • GetEmployees

      SELECT EmployeeID, LastName, FirstName,
      Title, HireDate, ReportsTo, Country
      FROM Employees
    • GetEmployeesByManager

      SELECT EmployeeID, LastName, FirstName,
      Title, HireDate, ReportsTo, Country
      FROM Employees
      WHERE ReportsTo = @ManagerID
    • GetEmployeeByEmployeeID

      SELECT ployeeID, LastName, FirstName,
      Title, HireDate, ReportsTo, Country
      FROM Employees
      WHERE EmployeeID = @EmployeeID


ASP.NET2.0数据操作之创建数据访问层(4)
图31:添加了四个TableAdapter后的DataSet设计器

  给DAL添加定制编码

  添加到强类型DataSet中的TableAdapter和DataTable是在一个XML Schema定义文 件(Northwind.xsd)中定义的。你可以在解决方案资源管理器里在Northwind.xsd 文件上按右鼠标,选择“查看编码(View Code)”,打开这个Schema文件来查看其中内容。

ASP.NET2.0数据操作之创建数据访问层(4)
图32:Northwinds强类型DataSet的XML Schema定义文件

  这个schema信息在设计时编译之后会被翻译成C#或Visual Basic 编码,或者如果有必要的话,会在运行时 翻译,然后你就能在调试器里单步遍历执行。想查看这些自动生成的编码的话,在类视图里,展 开TableAdapter 类或者强类型的DataSet 类。如果在屏幕上看不到类视图的话,在“查看”(View)菜单里选择“ 类视图”,或者按键组合Ctrl+Shift+C。在类视图里,你能看到强类型的DataSet类和TableAdapter类的属性,方法和事件。想看某个特定的方法的编码话,在类视图双击对应方法的名字或者在方法上按右鼠标,选 择“移至定义区(Go To Definition)”。

ASP.NET2.0数据操作之创建数据访问层(4)
图33:在类视图里选择“移至定义区(Go To Definition)”,查看自动生成的编码

  虽然自动生成的编码省时省力,但这样的编码往往是非常通用化的(generic),为满足一个应用程序特有的需 求需要做些定制。但扩展自动生成的编码的风险在于,如果生成这些编码的工具决定该是重新生成这些编码的 时候了,则会把你定制的编码冲掉。使用.NET 2.0中的一个新的部分(partial)类的概念,很容易将一个类的 定义分写在几个文件里。这允许我们给自动生成的类添加我们自己的方法,属性,和事件,而不用担心Visual Studio会冲掉我们的定制编码。

  为示范如何定制DAL起见,让我们来给SuppliersRow 添加一个GetProducts()方法。这 个SuppliersRow类代表了Suppliers表的个别记录,每个供应商(supplier)可以 提供0个到多个产品,所以GetProducts()将返回指定的供应商的这些产品。做法如 下,在App_Code文件夹里添加一个新的类文件,将其命名为SuppliersRow.cs, 然后在其中添加下列编码:

C#
1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            11

            12

            13

            14

            15

            16

            17

            
using System;

            using System.Data;

            using NorthwindTableAdapters;

            public partial class

            Northwind

            {

            public partial class

            SuppliersRow

            {

            public Northwind.ProductsDataTable GetProducts()

            {

            ProductsTableAdapter productsAdapter =

            new ProductsTableAdapter();

            return

            productsAdapter.GetProductsBySupplierID(this.SupplierID);

            }

            }

            }

            


  这个部分(partial)类指示编译器在编译Northwind.SuppliersRow类时,应该包含我们刚定义的这个GetProducts()方法。如果你编译你的项目,然后返回类视图,你就会看到GetProducts()已被列为Northwind.SuppliersRow的一个方法。

ASP.NET2.0数据操作之创建数据访问层(4)
图34: GetProducts()方法成为Northwind.SuppliersRow类的一部 分

  GetProducts()方法现在就能用来枚举一个指定供应商的产品列单,如下列编码所示:

C#
1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            11

            12

            13

            14

            15

            16

            17

            18

            19

            
NorthwindTableAdapters.SuppliersTableAdapter

            suppliersAdapter = new

            NorthwindTableAdapters.SuppliersTableAdapter();

            // Get all of the suppliers

            Northwind.SuppliersDataTable suppliers =

            suppliersAdapter.GetSuppliers();

            // Enumerate the suppliers

            foreach (Northwind.SuppliersRow supplier in suppliers)

            {

            Response.Write("Supplier: " +

            supplier.CompanyName);

            Response.Write("<ul>");

            // List the products for this supplier

            Northwind.ProductsDataTable products = supplier.GetProducts();

            foreach (Northwind.ProductsRow product in products)

            Response.Write("<li>" +

            product.ProductName + "</li>");

            Response.Write("</ul><p> </p>");

            }

            


  This data can also be displayed in any of ASP.NET's data Web controls. The following page uses a GridView control with two fields:数据也可以在任何一种ASP.NET的Web控件中显示。下面这个网页 使用了含有2个字段的GridView 控件:

  • 一个BoundField用以显示每个供应商的名字,
  • 另一个TemplateField,包含了一个BulletedList控件,用来绑定针对每个供应商调用 的GetProducts()方法返回的结果

  我们将在以后的教程里讨论怎样来显示这样的主/从(master-detail)报表。在这里,这个例子的目的是用 来示范如何使用添加到Northwind.SuppliersRow类中的自定义的方法的。

SuppliersAndProducts.aspx

ASP.NET
1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            11

            12

            13

            14

            15

            16

            17

            18

            19

            20

            21

            22

            23

            24

            25

            26

            27

            28

            29

            30

            31

            32

            33

            34

            35

            36

            37

            38

            39

            40

            41

            
<%@ Page Language="C#"

            AutoEventWireup="true" CodeFile="SuppliersAndProducts.aspx.cs"

            Inherits="SuppliersAndProducts" %>

            <!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>Untitled Page</title>

            <link href="Styles.css"

            rel="stylesheet"

            type="text/css"

            />

            </head>

            <body>

            <form id="form1" runat="server">

            <div>

            <h1>

            Suppliers and Their Products</h1>

            <p>

            <asp:GridView ID="GridView1" runat="server"

            AutoGenerateColumns="False"

            CssClass="DataWebControlStyle">

            <HeaderStyle CssClass="HeaderStyle" />

            <AlternatingRowStyle CssClass="AlternatingRowStyle" />

            <Columns>

            <asp:BoundField DataField="CompanyName"

            HeaderText="Supplier" />

            <asp:TemplateField HeaderText="Products">

            <ItemTemplate>

            <asp:BulletedList ID="BulletedList1"

            runat="server" DataSource="<%#

            ((Northwind.SuppliersRow)((System.Data.DataRowView)

            Container.DataItem).Row).GetProducts() %>"

            DataTextField="ProductName">

            </asp:BulletedList>

            </ItemTemplate>

            </asp:TemplateField>

            </Columns>

            </asp:GridView>

             </p>

            </div>

            </form>

            </body>

            </html>

            


SuppliersAndProducts.aspx.cs

C#
1

            2

            3

            4

            5

            6

            7

            8

            9

            10

            11

            12

            13

            14

            15

            16

            17

            18

            19

            20

            21

            22

            
using System;

            using System.Data;

            using System.Configuration;

            using System.Collections;

            using System.Web;

            using System.Web.Security;

            using System.Web.UI;

            using System.Web.UI.WebControls;

            using System.Web.UI.WebControls.WebParts;

            using System.Web.UI.HtmlControls;

            using NorthwindTableAdapters;

            public partial class

            SuppliersAndProducts : System.Web.UI.Page

            {

            protected void

            Page_Load(object sender, EventArgs e)

            {

            SuppliersTableAdapter suppliersAdapter = new

            SuppliersTableAdapter();

            GridView1.DataSource = suppliersAdapter.GetSuppliers();

            GridView1.DataBind();

            }

            }

            


ASP.NET2.0数据操作之创建数据访问层(4)
图 35: 供应商的公司名字列在左栏,他们的产品列在右栏

  总结

  构造web应用时,创建DAL应该是你最先做的步骤之一,应该在你开始创建表现层之前进行。使用Visual Studio的话,创建基于强类型DataSet的DAL是个可以不写一行编码,在10到15分钟内就可完成的任务。以后的 教程将建立在这个DAL基础之上。在下一个教程里,我们将定义一堆业务规则,然后看一下如何在一个分开的 业务逻辑层里实现这些规则。

你可能感兴趣的:(asp.net)