现在的位置: 首页 > 综合 > 正文

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

2012年05月20日 ⁄ 综合 ⁄ 共 8538字 ⁄ 字号 评论关闭
第五步:完成数据访问层

  注意,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
            


图29: 更新GetProducts()方法的SELECT语句

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


图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


图31:添加了四个TableAdapter后的DataSet设计器

  给DAL添加定制编码

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


图32:Northwinds强类型DataSet的XML Schema定义文件

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


图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的一个方法。


图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();
            }
            }
            


图 35: 供应商的公司名字列在左栏,他们的产品列在右栏

  总结

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

抱歉!评论已关闭.