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

80酷酷网    80kuku.com

  asp.net|创建|访问|数据  第五步:完成数据访问层

  注意,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 
     ProductID, ProductName, SupplierID, CategoryID, QuantityPerUnit, UnitPrice, UnitsInStock, UnitsOnOrder, ReorderLevel, Discontinued, ( CategoryName  Categories  Categories.CategoryID = Products.CategoryID)  CategoryName, ( CompanyName  Suppliers  Suppliers.SupplierID = Products.SupplierID)  SupplierName          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基础之上。在下一个教程里,我们将定义一堆业务规则,然后看一下如何在一个分开的 业务逻辑层里实现这些规则。

分享到
  • 微信分享
  • 新浪微博
  • QQ好友
  • QQ空间
点击: