成人性生交大片免费看视频r_亚洲综合极品香蕉久久网_在线视频免费观看一区_亚洲精品亚洲人成人网在线播放_国产精品毛片av_久久久久国产精品www_亚洲国产一区二区三区在线播_日韩一区二区三区四区区区_亚洲精品国产无套在线观_国产免费www

主頁 > 知識庫 > 在ASP.NET 2.0中操作數(shù)據(jù)之二:創(chuàng)建一個業(yè)務(wù)邏輯層

在ASP.NET 2.0中操作數(shù)據(jù)之二:創(chuàng)建一個業(yè)務(wù)邏輯層

熱門標(biāo)簽:天心智能電銷機器人 400電話辦理哪家性價比高 遂寧市地圖標(biāo)注app 代理接電話機器人如何取消 地圖標(biāo)注的公司有哪些 濮陽外呼電銷系統(tǒng)怎么樣 地圖定位圖標(biāo)標(biāo)注 塔城代理外呼系統(tǒng) 地圖標(biāo)注專業(yè)團隊

導(dǎo)言

  本教程的第一節(jié)所描述的數(shù)據(jù)訪問層(Data Access Layer,以下簡稱為DAL)已經(jīng)清晰地將表示邏輯與數(shù)據(jù)訪問邏輯區(qū)分開了。不過,即使DAL將數(shù)據(jù)訪問的細節(jié)從表示層中分離出來了,可它卻不能處理任何的業(yè)務(wù)規(guī)則。比如說,我們可能不希望產(chǎn)品表中那些被標(biāo)記為“停用”的產(chǎn)品的“分類編號”或“供應(yīng)商編號”被更新;我們還可能需要應(yīng)用一些資歷規(guī)則,比如說我們都不希望被比自己的資歷還要淺的人管理。另外一個比較常見的情況就是授權(quán),比如說只有那些具有特殊權(quán)限的用戶可以刪除產(chǎn)品或是更改單價。

  我們其實可以將業(yè)務(wù)邏輯層(Business Logic Layer,以下簡稱BLL)看作是在數(shù)據(jù)訪問層和表示層之間進行數(shù)據(jù)交換的橋梁,在這個章節(jié)中,我們將討論一下如何將這些業(yè)務(wù)規(guī)則集成到一個BLL中。需要說明的是,在一個實際的應(yīng)用程序中,BLL都是以類庫(Class Library)的形式來實現(xiàn)的,不過為了簡化工程的結(jié)構(gòu),在本教程中我們將BLL實現(xiàn)為App_Code文件夾中的一系列的類。圖一向我們展示了表示層、BLL以及DAL三者之間的結(jié)構(gòu)關(guān)系。

圖一:BLL將表示層與DAL隔開了,并且加入了業(yè)務(wù)規(guī)則

第一步:創(chuàng)建BLL類

  我們的BLL由4個類組成,每一個BLL類都對應(yīng)DAL中的一個TableAdapter,它們都從各自的TableAdapter中得到讀取、插入、修改以及刪除等方法以應(yīng)用合適的業(yè)務(wù)規(guī)則。

  為了更加清晰的區(qū)分DAL和BLL的類,我們在App_Code文件夾中建立兩個子文件夾,分別命名為DAL和BLL。你僅僅需要在解決方案瀏覽器(Solution Explorer)中右鍵點擊App_Code文件夾,并選擇新建文件夾(New Folder),就可以創(chuàng)建新的子文件夾了。建好了這兩個文件夾之后,把第一節(jié)中所創(chuàng)建的類型化數(shù)據(jù)集(Typed DataSet)移到DAL文件夾中。

  然后,在BLL文件夾中創(chuàng)建4個類文件。同樣,你僅僅需要在解決方案瀏覽器(Solution Explorer)中右鍵點擊BLL文件夾,并選擇新建項目(New Item),然后在彈出的對話框中選擇類模板(Class template)就可以創(chuàng)建新的類文件了。將這四個文件分別命名為ProductsBLL、CategoriesBLL、SuppliersBLL以及EmployeesBLL。

圖二:在BLL文件夾中添加4個新的類

  接下來,讓我們來給這些新建的類加上一些方法,簡單的將第一節(jié)中的TableAdapter中的那些方法包裝起來就行了?,F(xiàn)在,這些方法將只能直接使用DAL中的那些方法,我們等會再來給他們加上一些業(yè)務(wù)邏輯。

注意:如果你使用的是Visual Studio 標(biāo)準(zhǔn)版或以上版本(也就是說,你不是用的Visual Web Developer),那么你還可以使用
在ProductsBLL類中,我們一共需要為其添加7個方法:
GetProducts() – 返回所有的產(chǎn)品
GetProductByProductID(productID) – 返回指定ProductID的產(chǎn)品
GetProductsByCategoryID(categoryID) –返回指定分類的產(chǎn)品
GetProductsBySupplier(supplierID) –返回指定供應(yīng)商的產(chǎn)品
AddProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued) – 向數(shù)據(jù)庫中添加一條產(chǎn)品信息,并返回新添加的產(chǎn)品的ProductID
UpdateProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued, productID) – 更新一個數(shù)據(jù)庫中已經(jīng)存在的產(chǎn)品,如果剛好更新了一條記錄,則返回true,否則返回false
DeleteProduct(productID) – 刪除指定ProductID的產(chǎn)品

using System;
using System.Data;
using System.Configuration;
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;

[System.ComponentModel.DataObject]
public class ProductsBLL
{
 private ProductsTableAdapter _productsAdapter = null;
 protected ProductsTableAdapter Adapter
 {
 get {
  if (_productsAdapter == null)
  _productsAdapter = new ProductsTableAdapter();

  return _productsAdapter; 
 }
 }


 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, true)]
 public Northwind.ProductsDataTable GetProducts()
 { 
 return Adapter.GetProducts();
 }

 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
 public Northwind.ProductsDataTable GetProductByProductID(int productID)
 {
 return Adapter.GetProductByProductID(productID);
 }

 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
 public Northwind.ProductsDataTable GetProductsByCategoryID(int categoryID)
 {
 return Adapter.GetProductsByCategoryID(categoryID);
 }

 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Select, false)]
 public Northwind.ProductsDataTable GetProductsBySupplierID(int supplierID)
 {
 return Adapter.GetProductsBySupplierID(supplierID);
 }
 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Insert, true)]
 public bool AddProduct(string productName, int? supplierID, int? categoryID, string quantityPerUnit, 
    decimal? unitPrice, short? unitsInStock, short? unitsOnOrder, short? reorderLevel, 
    bool discontinued)
 {
 // 新建一個ProductRow實例
 Northwind.ProductsDataTable products = new Northwind.ProductsDataTable();
 Northwind.ProductsRow product = products.NewProductsRow();

 product.ProductName = productName;
 if (supplierID == null) product.SetSupplierIDNull(); else product.SupplierID = supplierID.Value;
 if (categoryID == null) product.SetCategoryIDNull(); else product.CategoryID = categoryID.Value;
 if (quantityPerUnit == null) product.SetQuantityPerUnitNull(); else product.QuantityPerUnit = quantityPerUnit;
 if (unitPrice == null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value;
 if (unitsInStock == null) product.SetUnitsInStockNull(); else product.UnitsInStock = unitsInStock.Value;
 if (unitsOnOrder == null) product.SetUnitsOnOrderNull(); else product.UnitsOnOrder = unitsOnOrder.Value;
 if (reorderLevel == null) product.SetReorderLevelNull(); else product.ReorderLevel = reorderLevel.Value;
 product.Discontinued = discontinued;

 // 添加新產(chǎn)品
 products.AddProductsRow(product);
 int rowsAffected = Adapter.Update(products);

 // 如果剛好新增了一條記錄,則返回true,否則返回false
 return rowsAffected == 1;
 }

 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, true)]
 public bool UpdateProduct(string productName, int? supplierID, int? categoryID, string quantityPerUnit,
    decimal? unitPrice, short? unitsInStock, short? unitsOnOrder, short? reorderLevel,
    bool discontinued, int productID)
 {
 Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
 if (products.Count == 0)
  // 沒有找到匹配的記錄,返回false
  return false;

 Northwind.ProductsRow product = products[0];

 product.ProductName = productName;
 if (supplierID == null) product.SetSupplierIDNull(); else product.SupplierID = supplierID.Value;
 if (categoryID == null) product.SetCategoryIDNull(); else product.CategoryID = categoryID.Value;
 if (quantityPerUnit == null) product.SetQuantityPerUnitNull(); else product.QuantityPerUnit = quantityPerUnit;
 if (unitPrice == null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value;
 if (unitsInStock == null) product.SetUnitsInStockNull(); else product.UnitsInStock = unitsInStock.Value;
 if (unitsOnOrder == null) product.SetUnitsOnOrderNull(); else product.UnitsOnOrder = unitsOnOrder.Value;
 if (reorderLevel == null) product.SetReorderLevelNull(); else product.ReorderLevel = reorderLevel.Value;
 product.Discontinued = discontinued;

 // 更新產(chǎn)品記錄
 int rowsAffected = Adapter.Update(product);

 // 如果剛好更新了一條記錄,則返回true,否則返回false
 return rowsAffected == 1;
 }

 [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Delete, true)]
 public bool DeleteProduct(int productID)
 {
 int rowsAffected = Adapter.Delete(productID);

 // 如果剛好刪除了一條記錄,則返回true,否則返回false
 return rowsAffected == 1;
 }
}

  GetProducts、GetProductByProductID、GetProductsByCategoryID以及 GetProductBySuppliersID等方法都僅僅是簡簡單單的直接調(diào)用DAL中的方法來返回數(shù)據(jù)。不過在有的情況下,我們還可能需要給它們實現(xiàn)一些業(yè)務(wù)規(guī)則(比如說授權(quán)規(guī)則,不同的用戶或不用角色應(yīng)該可以看到不同的數(shù)據(jù)),現(xiàn)在我們簡單的將它們做成這樣就可以了。那么,對于這些方法來說,BLL僅僅是作為表示層與DAL之間的代理。

  AddProduct和UpdateProduct這兩個方法都使用參數(shù)中的那些產(chǎn)品信息去添加或是更新一條產(chǎn)品記錄。由于Product表中有許多字段都允許空值(CategoryID、SupplierID、UnitPrice……等等),所以AddProduct和UpdateProduct中相應(yīng)的參數(shù)就使用nullable types。Nullable types是.NET 2.0中新提供的一種用于標(biāo)明一個值類型是否可以為空的技術(shù)。在C#中,你可以在一個允許為空的值類型后面加上一個問號(比如,int? x;)。關(guān)于Nullable Types的詳細信息,你可以參考C# Programming Guide。

  由于插入、修改和刪除可能不會影響任何行,所以這三種方法均返回一個bool值用于表示操作是否成功。比如說,頁面開發(fā)人員使用一個并不存在的ProductID去調(diào)用DeleteProduct,很顯然,提交給數(shù)據(jù)庫的DELETE語句將不會有任何作用,所以DeleteProduct會返回false。

  注意:當(dāng)我們在添加或更新一個產(chǎn)品的詳細信息時,都是接受由產(chǎn)品信息組成的一個標(biāo)量列表,而不是直接接受一個ProductsRow實例。因為ProductsRow是繼承于ADO.NET的DataRow,而DataRow沒有默認的無參構(gòu)造函數(shù),為了創(chuàng)建一個ProductsRow的實例,我們必須先創(chuàng)建一個ProductsDataTable的實例,然后調(diào)用它的NewProductRow方法(就像我們在AddProduct方法中所做的那樣)。不過,當(dāng)我在使用ObjectDataSource來插入或更新時,這樣做的缺點就會暴露出來了。簡單的講,ObjectDataSource會試圖為輸入的參數(shù)創(chuàng)建一個實例,如果BLL方法希望得到一個ProductsRow,那么ObjectDataSource就將會試圖去創(chuàng)建一個,不過很顯然,這樣的操作一定會失敗,因為沒有一個默認的無參構(gòu)造函數(shù)。這個問題的詳細信息,可以在ASP.NET論壇的以下兩個帖子中找到: Updating ObjectDataSources with Strongly-Typed DataSets、Problem With ObjectDataSource and Strongly-Typed DataSet。

  之后,在AddProduct和UpdateProduct中,我們創(chuàng)建了一個ProductsRow實例,并將傳入的參數(shù)賦值給它。當(dāng)給一個DataRow的DataColumns賦值時,各種字段級的有效性驗證都有可能會被觸發(fā)。因此,我們應(yīng)該手工的驗證一下傳入的參數(shù)以保證傳遞給BLL方法的數(shù)據(jù)是有效的。不幸的是,Visual Studio生成的強類型數(shù)據(jù)集(strongly-typed DataRow)并沒有使用nullable values。要表明DataRow中的一個DataColumn可以接受空值,我們就必須得使用SetColumnNameNull方法。

  在UpdateProduct中,我們先使用GetProductByProductID(productID)方法將需要更新的產(chǎn)品信息讀取出來。這樣做好像沒有什么必要,不過我們將在之后的關(guān)于并發(fā)優(yōu)化(Optimistic concurrency)的課程中證明這個額外的操作是有它的作用的。并發(fā)優(yōu)化是一種保證兩個用戶同時操作一個數(shù)據(jù)而不會發(fā)生沖突的技術(shù)。獲取整條記錄同時也可以使創(chuàng)建一個僅更新DataRow的一部分列的方法更加容易,我們可以在SuppliersBLL類中找到這樣的例子。

  最后,注意我們在ProductsBLL類上面加上了DataObject 標(biāo)簽(就是在類聲明語句的上面的[System.ComponentModel.DataObject]),各方法上面還有DataObjectMethodAttribute 標(biāo)簽。DataObject標(biāo)簽把這個類標(biāo)記為可以綁定到一個ObjectDataSource控件,而DataObjectMethodAttribute則說明了這個方法的目的。我們將在后面的教程中看到,ASP.NET 2.0的ObjectDataSource使從一個類中訪問數(shù)據(jù)更加容易。為了ObjectDataSource向?qū)軌驅(qū)ΜF(xiàn)有的類進行合適的篩選,在類列表中默認僅顯示標(biāo)記為DataObject的類。當(dāng)然,其實ProductsBLL類就算沒有這個標(biāo)簽也可以工作,但是加上它可以使我們在ObjectDataSource向?qū)е械牟僮鞲虞p松和心情愉快。

添加其他的類

  完成了ProductsBLL類之后,我們還要添加一些為categories、suppliers和employees服務(wù)的類。讓我們花點時間來創(chuàng)建下面的類,根據(jù)上面的例子來做就是了:

·CategoriesBLL.cs
    GetCategories()
    GetCategoryByCategoryID(categoryID)

·SuppliersBLL.cs
    GetSuppliers()
    GetSupplierBySupplierID(supplierID)
    GetSuppliersByCountry(country)
    UpdateSupplierAddress(supplierID, address, city, country)

·EmployeesBLL.cs
    GetEmployees()
    GetEmployeeByEmployeeID(employeeID)
    GetEmployeesByManager(managerID)

  SuppliersBLL類中的UpdateSupplierAddress方法是一個值得注意的東西。這個方法提供了一個僅僅更新供應(yīng)商地址信息的接口。它首先根據(jù)指定的SupplierID讀出一個SupplierDataRow(使用GetSupplierBySupplierID方法),設(shè)置其關(guān)于地址的所有屬性,然后調(diào)用SupplierDataTable的Update方法。UpdateSupplierAddress方法的代碼如下所示:

[System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, true)]
public bool UpdateSupplierAddress(int supplierID, string address, string city, string country)
{
 Northwind.SuppliersDataTable suppliers = Adapter.GetSupplierBySupplierID(supplierID);
 if (suppliers.Count == 0)
 // 沒有找到匹配的項,返回false
 return false;
 else
 {
 Northwind.SuppliersRow supplier = suppliers[0];

 if (address == null) supplier.SetAddressNull(); else supplier.Address = address;
 if (city == null) supplier.SetCityNull(); else supplier.City = city;
 if (country == null) supplier.SetCountryNull(); else supplier.Country = country;

 // 更新供應(yīng)商的關(guān)于地址的信息
 int rowsAffected = Adapter.Update(supplier);

 // 如果剛好更新了一條記錄,則返回true,否則返回false
 return rowsAffected == 1;
 }
}

可以從頁面頂部的鏈接處下載BLL類的完整代碼。

第二步:通過BLL類訪問類型化數(shù)據(jù)集

在本教程的第一節(jié)中,我們給出了直接使用類型化數(shù)據(jù)集的例子,不過在我們添加了BLL類之后,表示層就可以通過BLL來工作了。在本教程的第一節(jié)中的AllProducts.aspx的例子中,ProductsTableAdapter用于將產(chǎn)品列表綁定到GridView上,代碼如下所示:

ProductsTableAdapter productsAdapter = new ProductsTableAdapter();
GridView1.DataSource = productsAdapter.GetProducts();
GridView1.DataBind();

要使用新的BLL類,我們所需要做的僅僅是簡單的修改一下第一行代碼。用ProductBLL對象來代替 ProductsTableAdapter即可:

ProductsBLL productLogic = new ProductsBLL();
GridView1.DataSource = productLogic.GetProducts();
GridView1.DataBind();

BLL類也可以通過使用ObjectDataSource來清晰明了的訪問(就像類型化數(shù)據(jù)集一樣)。我們將在接下來的教程中詳細的討論ObjectDataSource。

圖三:GridView中顯示的產(chǎn)品列表

第三步:給DataRow添加字段級驗證

字段級驗證是指在插入或更新時檢查業(yè)務(wù)對象所涉及到的所有屬性值。拿產(chǎn)品來舉個例,某些字段級的驗證規(guī)則如下所示:
·ProductName字段不得超過40個字符
·QuantityPerUnit字段不得超過20個字符
·ProductID、ProductName以及Discontinued字段是必填的,而其他字段則是可填可不填的
·UnitPrice、UnitsInStock、UnitsOnOrder以及ReorderLevel字段不得小于0

  這些規(guī)則可以或者說是應(yīng)該在數(shù)據(jù)庫層被描述出來。ProductName和QuantityPerUnit字段上的字符數(shù)限制可以通過Products表中相應(yīng)列的數(shù)據(jù)類型來實現(xiàn)(分別為nvarchar(40) and nvarchar(20))。字段“是否必填”可以通過將數(shù)據(jù)庫中表的相應(yīng)列設(shè)置為“允許為NULL”來實現(xiàn)。為了保證UnitPrice、UnitsInStock、UnitsOnOrder以及ReorderLevel字段的值不小于0,可以分別在它們的相應(yīng)列上加一個約束。
除了在數(shù)據(jù)庫中應(yīng)用了這些規(guī)則之外,它們同時也將被其應(yīng)用在DataSet上。事實上,字段長度和是否允許為空等信息已經(jīng)被應(yīng)用到了各DataTable的DataColumn集合中。我們可以在數(shù)據(jù)集設(shè)計器(DataSet Designer)中看到已經(jīng)存在的字段級驗證,從某個DataTable中選擇一個字段,然后在屬性窗口中就可以找到了。如圖四所示,ProductDataTable中的QuantityPerUnit字段允許空值并且最大長度為20各字符。如果我們試圖給某個ProductsDataRow的QuantityPerUnit屬性設(shè)置一個長度大于20個字符的字符串,將會有一個ArgumentException被拋出。

圖四:DataColumn提供了基本的字段級驗證

  不幸的是,我們不能通過屬性窗口指定一個邊界檢查,比如UnitPrice的值不能小于0。為了提供這樣的字段級驗證,我們需要為DataTable的ColumnChanging事件建立一個Event Handler。正如上一節(jié)教程中所提到的那樣,由類型化數(shù)據(jù)集創(chuàng)建的DataSet、DataTable還有DataRow對象可以通過partial類來進行擴展。使用這個技術(shù),我們可以為ProductDataTable創(chuàng)建一個ColumnChanging的Event Handler。我們先在App_Code文件夾中新建一個名為ProductsDataTable.ColumnChanging.cs的類文件,如下圖所示。

圖五:在App_Code文件夾中添加新類

  然后,給ColumnChanging事件創(chuàng)建一個Event handler,以保證UnitPrice、UnitsInStock、UnitsOnOrder以及ReorderLevel字段的值不小于0。如果這些列的值超出范圍就拋出一個ArgumentException。

public partial class Northwind
{
 public partial class ProductsDataTable
 {
 public override void BeginInit()
  {
  this.ColumnChanging += ValidateColumn;
  }

  void ValidateColumn(object sender, DataColumnChangeEventArgs e)
  {
  if(e.Column.Equals(this.UnitPriceColumn))
  {
  if(!Convert.IsDBNull(e.ProposedValue)  (decimal)e.ProposedValue  0)
  {
   throw new ArgumentException("UnitPrice cannot be less than zero", "UnitPrice");
  }
  }
  else if (e.Column.Equals(this.UnitsInStockColumn) ||
   e.Column.Equals(this.UnitsOnOrderColumn) ||
   e.Column.Equals(this.ReorderLevelColumn))
  {
  if (!Convert.IsDBNull(e.ProposedValue)  (short)e.ProposedValue  0)
  {
   throw new ArgumentException(string.Format("{0} cannot be less than zero", e.Column.ColumnName), e.Column.ColumnName);
  }
  }
  }
 }
}

第四步:給BLL類添加業(yè)務(wù)規(guī)則

除了字段級的驗證,可能還有一些不能在單個列中表示的包含不同實體或概念的更高級的業(yè)務(wù)規(guī)則,比如:
·如果一個產(chǎn)品被標(biāo)記為“停用”,那么它的單價就不能被修改
·一個雇員的居住地必須與他(她)的主管的居住地相同
·如果某個產(chǎn)品是某供應(yīng)商唯一提供的產(chǎn)品,那么這個產(chǎn)品就不能被標(biāo)記為“停用”

  BLL類應(yīng)該保證始終都驗證應(yīng)用程序的業(yè)務(wù)規(guī)則。這些驗證可以直接的添加到應(yīng)用他們的方法中。
想象一下,我們的業(yè)務(wù)規(guī)則表明了如果一個產(chǎn)品是給定的供應(yīng)商的唯一產(chǎn)品,那么它就不能被標(biāo)記為“停用”。也就是說,如果產(chǎn)品X是我們從供應(yīng)商Y處購買的唯一一個產(chǎn)品,那么我們就不能將X標(biāo)記為停用;然而,如果供應(yīng)商Y提供給我們的一共有3樣產(chǎn)品,分別是A、B和C,那么我們可以將其中任何一個或者三個全部都標(biāo)記為“停用”。挺奇怪的業(yè)務(wù)規(guī)則,是吧?但是商業(yè)上的規(guī)則通常就是跟我們平常的感覺不太一樣。

  要在UpdateProducts方法中應(yīng)用這個業(yè)務(wù)規(guī)則,那么我們就應(yīng)該先檢查Discontinued是否被設(shè)置為true。假如是這樣的話,那么我們應(yīng)該先調(diào)用GetProductsBySupplierID來看看我們從這個供應(yīng)商處一共購買了多少產(chǎn)品。如果我們僅僅從這個供應(yīng)商處購買了這一個產(chǎn)品,那么我們就拋出一個ApplicationException。

public bool UpdateProduct(string productName, int? supplierID, int? categoryID, string quantityPerUnit,
    decimal? unitPrice, short? unitsInStock, short? unitsOnOrder, short? reorderLevel,
    bool discontinued, int productID)
{
 Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
 if (products.Count == 0)
  // 沒有找到匹配項,返回false
  return false;

 Northwind.ProductsRow product = products[0];

 // 業(yè)務(wù)規(guī)則檢查 – 不能停用某供應(yīng)商所提供的唯一一個產(chǎn)品
 if (discontinued)
 {
  // 獲取我們從這個供應(yīng)商處獲得的所有產(chǎn)品
  Northwind.ProductsDataTable productsBySupplier = Adapter.GetProductsBySupplierID(product.SupplierID);

  if (productsBySupplier.Count == 1)
  // 這是我們從這個供應(yīng)商處獲得的唯一一個產(chǎn)品
  throw new ApplicationException("You cannot mark a product as discontinued if its the only product purchased from a supplier");
 }

 product.ProductName = productName;
 if (supplierID == null) product.SetSupplierIDNull(); else product.SupplierID = supplierID.Value;
 if (categoryID == null) product.SetCategoryIDNull(); else product.CategoryID = categoryID.Value;
 if (quantityPerUnit == null) product.SetQuantityPerUnitNull(); else product.QuantityPerUnit = quantityPerUnit;
 if (unitPrice == null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value;
 if (unitsInStock == null) product.SetUnitsInStockNull(); else product.UnitsInStock = unitsInStock.Value;
 if (unitsOnOrder == null) product.SetUnitsOnOrderNull(); else product.UnitsOnOrder = unitsOnOrder.Value;
 if (reorderLevel == null) product.SetReorderLevelNull(); else product.ReorderLevel = reorderLevel.Value;
 product.Discontinued = discontinued;

 // 更新產(chǎn)品記錄
 int rowsAffected = Adapter.Update(product);

 // 如果剛好更新了一條記錄,則返回true,否則返回false
 return rowsAffected == 1;
}

在表示層中響應(yīng)驗證錯誤

  當(dāng)我們從表示層中調(diào)用BLL時,我們可以決定是否要處理某個可能會被拋出的異常或者讓它直接拋給ASP.NET(這樣將會引發(fā)HttpApplication的出錯事件)。在使用BLL的時候,如果要以編程的方式處理一個異常,我們可以使用try...catch塊,就像下面的示例一樣:

ProductsBLL productLogic = new ProductsBLL();

// 更新ProductID為1的產(chǎn)品信息

try
{
 // 這個操作將會失敗,因為我們試圖使用一個小于0的UnitPrice
 productLogic.UpdateProduct("Scott's Tea", 1, 1, null, -14m, 10, null, null, false, 1);
}
catch (ArgumentException ae)
{
 Response.Write("There was a problem: " + ae.Message);
}

  我們將在后面的教程中看到,當(dāng)通過一個數(shù)據(jù)Web控件(data Web Control)來進行插入、修改或刪除操作數(shù)據(jù)時,處理從BLL中拋出的異??梢灾苯釉谝粋€Event Handler中進行,而不需要使用try…catch塊來包裝代碼。

總結(jié)

  一個具有良好架構(gòu)的應(yīng)用程序都擁有清晰的層次結(jié)構(gòu),每一個層次都封裝了一個特定的角色。在本教程的第一篇中,我們用類型化數(shù)據(jù)集創(chuàng)建了一個數(shù)據(jù)訪問層;這一篇中,我們又建立了一個業(yè)務(wù)邏輯層,它由App_Code中一系列的類構(gòu)成,并調(diào)用DAL中相應(yīng)的方法。BLL為我們的應(yīng)用程序?qū)崿F(xiàn)了字段級和業(yè)務(wù)級的邏輯。除了創(chuàng)建一個獨立的BLL,就像我們在本節(jié)中所做的那樣,另外一個選擇是使用partial類來擴展TableAdapter中的方法。然而,使用這個技術(shù)并不能使我們可以重寫已經(jīng)存在的方法,也不能將我們的DAL和BLL分開得足夠清晰。

  完成了DAL和BLL之后,我們就準(zhǔn)備開始處理表示層了。在下一個教程中,我們將簡單的介紹一些數(shù)據(jù)訪問的主題,并為整個教程定義一個一致的頁面呈現(xiàn)。
編程愉快!

關(guān)于作者
Scott Mitchell,著有六本ASP/ASP.NET方面的書,是4GuysFromRolla.com的創(chuàng)始人,自1998年以來一直應(yīng)用微軟Web技術(shù)。Scott是個獨立的技術(shù)咨詢顧問,培訓(xùn)師,作家,最近完成了將由Sams出版社出版的新作,24小時內(nèi)精通ASP.NET 2.0。他的聯(lián)系電郵為mitchell@4guysfromrolla.com,也可以通過他的博客http://ScottOnWriting.NET與他聯(lián)系。

您可能感興趣的文章:
  • 在ASP.NET 2.0中操作數(shù)據(jù)之一:創(chuàng)建一個數(shù)據(jù)訪問層
  • 在ASP.NET 2.0中操作數(shù)據(jù)之三:創(chuàng)建母版頁和站點導(dǎo)航
  • 在ASP.NET 2.0中操作數(shù)據(jù)之四:使用ObjectDataSource展現(xiàn)數(shù)據(jù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之五:聲明參數(shù)
  • 在ASP.NET 2.0中操作數(shù)據(jù)之六:編程設(shè)置ObjectDataSource的參數(shù)值
  • ASP.NET 2.0中的數(shù)據(jù)操作之七:使用DropDownList過濾的主/從報表
  • ASP.NET 2.0中的數(shù)據(jù)操作之八:使用兩個DropDownList過濾的主/從報表
  • ASP.NET 2.0中的數(shù)據(jù)操作之九:跨頁面的主/從報表
  • 在ASP.NET 2.0中操作數(shù)據(jù)之十:使用 GridView和DetailView實現(xiàn)的主/從報表
  • [翻譯]Scott Mitchell 的ASP.NET 2.0數(shù)據(jù)教程

標(biāo)簽:麗江 婁底 重慶 本溪 汕頭 河南 吉林 宜春

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《在ASP.NET 2.0中操作數(shù)據(jù)之二:創(chuàng)建一個業(yè)務(wù)邏輯層》,本文關(guān)鍵詞  在,ASP.NET,2.0,中,操作,數(shù)據(jù),;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《在ASP.NET 2.0中操作數(shù)據(jù)之二:創(chuàng)建一個業(yè)務(wù)邏輯層》相關(guān)的同類信息!
  • 本頁收集關(guān)于在ASP.NET 2.0中操作數(shù)據(jù)之二:創(chuàng)建一個業(yè)務(wù)邏輯層的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    国产精品免费在线| 99久久综合狠狠综合久久止| 亚洲国产成人av好男人在线观看| 中文字幕有码视频| 欧美金发大战黑人最粗videos| 国产一级精品在线| 精品视频在线一区二区在线| 国产精品久久午夜夜伦鲁鲁| 亚洲欧洲成人精品av97| 91free张津瑜movies| 肉色欧美久久久久久久免费看| 这里有精品可以观看| 日本夜夜草视频网站| 日韩精品中文字幕吗一区二区| 在线电影一区二区三区| 亚洲精品美女在线观看播放| 中国日本在线视频中文字幕| 久久手机视频| 日本熟妇色xxxxx日本免费看| 久久人人爽人人爽爽久久| 精品中文字幕一区二区小辣椒| 精品久久久久久国产91| 亚洲精品美国一| 欧美成人一区二区在线| 美女福利一区二区三区| 欧美日韩二区三区| 中文字幕在线观看91| 在线看国产视频| 欧美三级一区| 国产精品videossex| 欧美成人精品一区二区男人看| 欧美午夜免费影院| 一二三四视频社区在线| 色欲av无码一区二区三区| 国产日韩欧美精品一区| 在线观看不卡一区| 国产日韩精品入口| 在线观看av一区| 欧美三级在线播放| 韩国国内大量揄拍精品视频| 国产一区二区三区四区五区加勒比| 亚洲综合色一区| 欧美成年人视频网站欧美| 中文字幕乱码在线观看| 亚洲精品视频在线看| 99精品视频在线播放观看| 亚洲女人毛茸茸高潮| 青娱乐国产精品| 中文字幕久热精品视频在线| 久久久久99精品成人片毛片| 妺妺窝人体色www婷婷| 免费在线视频一区二区| 欧美高清视频看片在线观看| 成人av电影在线网| 免费观看黄一级视频| 97一区二区国产好的精华液| 伊人免费在线观看高清版| 欧美性猛交xxxx乱大交少妇| 手机av免费观看| www污网站在线观看| 国产欧美自拍视频| 日韩精品亚洲aⅴ在线影院| 欧美日韩精品在线视频| 黄网在线免费看| 久久精品一区中文字幕| 久久99精品一区二区三区三区| 一本一道精品欧美中文字幕| 男裸体无遮挡网站| 色综合伊人色综合网站| 国产人久久人人人人爽| 久久偷窥视频| 精品一区二区三区免费播放| jiuse.com91视频| 亚洲国产欧美日韩在线| 亚洲精品456| 一个人免费观看视频www在线播放| 国外成人免费在线播放| 欧美中文娱乐网| 国产精品羞羞答答在线观看| 国产精品美女久久久久aⅴ| 免费高清完整在线观看| 偷拍盗摄高潮叫床对白清晰| 国产婷婷色一区二区在线观看| 日韩亚洲欧美中文三级| 成人免费网站www网站高清| 福利在线视频网站| 日韩国产欧美亚洲| 亚洲精品一区在线观看| 青青青爽久久午夜综合久久午夜| 精品成人乱色一区二区| 最好看更新中文字幕| 一区二区三区免费播放| 欧美1区2区3| xfplay每日更新av资源| 好吊妞www.84com只有这里才有精品| 97人妻精品一区二区三区免费| 精品国产一区二区三区久久狼5月| 亚洲午夜福利在线观看| 六月婷婷久久| 啊啊啊啊啊啊啊视频在线播放| 91农村精品一区二区在线| 国产精品久久久久精k8| 国产成人精品亚洲日本在线桃色| 亚洲激情视频网| 视频区小说区图片区| 亚洲区一区二区三区| 色网视频在线| 色777狠狠狠综合伊人| 99精品桃花视频在线观看| 国产夫妻性生活视频| 国色天香久久精品国产一区| 亚洲h动漫在线| 一本久道久久综合狠狠爱亚洲精品| 97视频在线免费观看| 亚洲精品国产精品国自产网站按摩| 26uuu久久噜噜噜噜| 久久久久久网址| 日本一区二区三区电影免费观看| 性色av一区二区三区免费| av在线不卡播放| 欧美精品97| 国产91欧美| 国产一区二区网| 欧美女激情福利| 成人午夜免费av| 欧美一卡二卡三卡四卡| 青青青伊人色综合久久| 成人av免费看| 中文字幕免费在线播放| 欧美videos另类精品| 国产亚洲日本欧美韩国| 亚洲男人在线| www.com.cn成人| 污污网站在线观看| 91成人高清| 色妞www精品视频| 在线中文资源天堂| 日韩精品免费观看视频| 麻豆传传媒久久久爱| 国产高清在线视频| 青春草在线视频| 欧美视频日韩视频| 蜜臀99久久精品久久久久小说| 香蕉97视频观看在线观看| 亚洲视频自拍偷拍| 国产毛片视频| 国产日产高清欧美一区二区三区| 亚洲毛片免费看| 天天综合天天做天天综合| 九九亚洲视频| 亚洲xxx大片| 美女黄视频在线观看| 欧美激情一区在线观看| 日韩不卡视频一区二区| 成人中文字幕av| 美国黄色小视频| 另类综合日韩欧美亚洲| 亚洲激情啪啪| 久久中文字幕电影| 国产农村妇女毛片精品| 日韩av一级电影| 亚洲色图日韩精品| 亚洲免费成人av电影| 欧美少妇网站| 日韩一级片免费在线观看| 国产一二三区在线播放| 中文字幕亚洲综合久久菠萝蜜| 国产偷窥老熟盗摄视频| 男女视频一区二区| 久久亚洲一区二区三区明星换脸| 亚洲啪av永久无码精品放毛片| xfplay爱情电影网love| 亚洲午夜色婷婷在线| 精品网站www| jizzjizz16| 美女大黄三级视频在线观看| 7777精品伊人久久久大香线蕉最新版| 欧美视频在线一区| 国产一区二区精品久久| 少妇无套高潮一二三区| 影音av资源网| 亚洲图片欧美午夜| 91九色丨porny丨国产jk| jizzjizz国产精品喷水| 久久国产精品亚洲va麻豆| 色先锋av男人资源先锋影院| 日韩视频在线观看一区| 国产稀缺精品盗摄盗拍| 国产一区二区精品福利地址| 向日葵视频成人app网址| 欧美精品91| 999在线精品视频| 亚洲国产高清视频| 性猛交富婆╳xxx乱大交一| jjzzjjzz欧美69巨大| 96视频在线观看欧美| 99久久亚洲国产日韩美女| 日韩污视频在线观看| 成人做爰69片免网站| 人妻视频一区二区三区| 欧美精品一卡二卡| 欧美一级爱爱| 成人日韩视频| 亚洲视频免费| 亚洲高清国产精品| 精品国产乱码久久久久软件| 欧美日韩国产成人在线| 日韩欧美少妇| 2023国产精华国产精品| 二区三区精品| 国产乱码字幕精品高清av| 国产真人做爰毛片视频直播| 亚洲va在线va天堂成人| 亚洲成人性视频| 日韩欧美看国产| 精品国产免费人成在线观看| 国产三区在线播放| 国产亚洲欧美久久久久| 啊v在线视频| 欧美日韩国产v| 制服丝袜亚洲网站| 日本熟女一区二区| 日韩精品免费在线播放| www.av在线| 日本japanese极品少妇| 日韩成人免费在线视频| 国产精品成人观看视频国产奇米| 97精品国产97久久久久久| 韩国v欧美v日本v亚洲v| 另类视频在线| 国产成人无码一区二区在线播放| 欧美亚洲成人免费| 中文字幕无码不卡免费视频| 免费视频二区| 亚洲欧美日韩小说| 右手影院亚洲欧美| 思思久久99热只有频精品66| 黄色片视频免费观看| 欧洲视频一区二区三区| 久久不射影院| 国产精品我不卡| 91精品国产色综合久久不8| 亚洲精品91| 成人激情av在线| 亚洲av成人精品一区二区三区在线播放| wwwxxx在线观看| 国产suv精品一区二区三区| 日本不卡二区高清三区| 爽死777影院| 91久久精品日日躁夜夜躁欧美| 日韩不卡免费高清视频| 手机在线视频一区| 色呦呦国产精品| 成人午夜无人区一区二区| 污污的视频网站在线观看| av超碰在线观看| av天天在线| 精品久久久999| 久99九色视频在线观看| 久久久久久久九九九九| 亚洲精品国产av| 亚洲91精品在线| 天堂精品一区二区三区| 久久er热在这里只有精品66| 国产精品中文| 中文字幕一区二区人妻电影| 美国黄色一级视频| 亚洲成人人体| 欧美视频在线观看一区| 欧美成人国产精品高潮| 亚洲天堂网中文字| av大片免费在线观看| 色综合久久久无码中文字幕波多| 性爱在线免费视频| 91在线资源| 另类成人小视频在线| www在线观看免费| 久久精品国产免费观看99| 国产精品一区免费在线观看| 在线观看av一区二区| 黄色成人在线观看网站| 亚洲图片欧美日产| 国产精品久久久久久99| 亚洲区成人777777精品| 国产米奇在线777精品观看| 影音先锋一区二区资源站| 日韩欧美在线视频| 99精品视频播放| 麻豆亚洲av熟女国产一区二| 国产精品久久久久久99| 欧美精品黑人猛交高潮| 欧美黄色大片在线观看| 欧美午夜影院在线视频| 免费看污网站| 青青在线视频免费| 美女在线视频一区| 欧美狂野另类xxxxoooo| 国产精品久久久久久av公交车| 天堂精品一区二区三区| 日韩一二三四| 欧美黄色影院| 在线观看三级网站| 中文字幕第100页| 欧美精品91| 福利在线视频导航| 欧美午夜不卡视频| 青青草97国产精品免费观看无弹窗版| 亚洲色图25p| 国产性猛交普通话对白| 美女少妇精品视频| 粉嫩久久久久久久极品| 亚洲 欧美 激情 小说 另类| 91香蕉嫩草影院入口| 国产区一区二区三区| 欧美日韩一二三四区| 精品一区二区三区的国产在线播放| 日本一区二区三区四区五区| 嫩草研究院在线| 暧暧视频在线免费观看| 2025韩国大尺度电影| 69精品国产久热在线观看| 无码人妻av免费一区二区三区| 亚洲裸体俱乐部裸体舞表演av| 极品尤物久久久av免费看| 婷婷激情五月综合| 中文字幕在线久热精品| 亚洲欧洲国产日韩精品| 综合网日日天干夜夜久久|