共用方式為


建立商業邏輯層 (C#)

作者:Scott Mitchell

下載 PDF

在本教學課程中,我們將瞭解如何將商務規則集中到商業規則層 (BLL) ,做為呈現層與 DAL 之間數據交換的媒介。

簡介

一個 教學課程中建立的數據存取層 (DAL) 會清楚分隔數據存取邏輯與表示邏輯。 不過,雖然 DAL 會清楚分隔數據存取詳細數據與呈現層,但不會強制執行任何可能套用的商務規則。 例如,針對我們的應用程式,我們可能會想要不允許CategoryID在欄位設定為 1 時Discontinued修改資料表的 ProductsSupplierID 欄位,或者我們可能會想要強制執行資深規則,禁止員工由員工在員工之後管理的情況。 另一個常見的案例可能是只有特定角色中的使用者可以刪除產品,或變更 UnitPrice 值。

在本教學課程中,我們將瞭解如何將這些商務規則集中到商業規則層 (BLL) ,做為呈現層與 DAL 之間數據交換的媒介。 在真實世界應用程式中,BLL 應該實作為個別的類別庫專案;不過,在這些教學課程中,我們將實作 BLL 作為資料夾中 App_Code 的一系列類別,以簡化項目結構。 圖 1 說明呈現層、BLL 和 DAL 之間的架構關聯性。

BLL 會將呈現層與數據存取層分開,並強制執行商務規則

圖 1:BLL 會將呈現層與數據存取層分開,並強制執行商務規則

步驟 1:建立 BLL 類別

我們的 BLL 會由四個類別組成,一個用於 DAL 中的每個 TableAdapter;每個 BLL 類別都有方法可從 DAL 中的個別 TableAdapter 擷取、插入、更新和刪除,並套用適當的商務規則。

為了更清楚分隔 DAL 和 BLL 相關類別,讓我們在 App_Code 資料夾中建立兩個子資料夾, DALBLL。 只要以滑鼠右鍵按兩下 App_Code 方案總管中的資料夾,然後選擇[新增資料夾]。 建立這兩個資料夾之後,請將第一個教學課程中建立的 DAL 具類型數據集移至子資料夾。

接下來,在子資料夾中建立四個 BLL BLL 類別檔案。 若要完成這項作業,請以滑鼠右鍵按兩下 BLL 子資料夾,選擇 [新增專案],然後選擇 [類別] 範本。 將四個類別 ProductsBLL命名為、 CategoriesBLLSuppliersBLLEmployeesBLL

將四個新類別新增至 App_Code資料夾

圖 2:將四個新類別新增至 App_Code 資料夾

接下來,讓我們將方法新增至每個類別,以直接包裝第一個教學課程中為 TableAdapters 定義的方法。 現在,這些方法只會直接呼叫 DAL;我們稍後會返回 ,以新增任何所需的商業規則。

注意

如果您使用 Visual Studio Standard Edition 或更新版本 (,則您不使用 Visual Web Developer) ,您可以選擇性地使用類別 Designer 以可視化方式設計類別。 如需 Visual Studio 中這項新功能的詳細資訊,請參閱類別 Designer 部落格

針對 類別, ProductsBLL 我們需要新增總共七個方法:

  • GetProducts() 傳回所有產品
  • GetProductByProductID(productID) 傳回具有指定產品標識碼的產品
  • GetProductsByCategoryID(categoryID) 傳回指定類別中的所有產品
  • GetProductsBySupplier(supplierID) 傳回指定供應商的所有產品
  • AddProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued) 使用傳入的值,將新產品插入資料庫中;傳 ProductID 回新插入記錄的值
  • UpdateProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued, productID) 使用傳入的值更新資料庫中的現有產品; true 如果精確更新一個數據列,則傳回 , false 否則傳回
  • DeleteProduct(productID) 從資料庫刪除指定的產品

ProductsBLL.cs

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)
    {
        // Create a new ProductRow instance
        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;

        // Add the new product
        products.AddProductsRow(product);
        int rowsAffected = Adapter.Update(products);

        // Return true if precisely one row was inserted,
        // otherwise 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)
            // no matching record found, return 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;

        // Update the product record
        int rowsAffected = Adapter.Update(product);

        // Return true if precisely one row was updated,
        // otherwise false
        return rowsAffected == 1;
    }

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

        // Return true if precisely one row was deleted,
        // otherwise false
        return rowsAffected == 1;
    }
}

只要傳回數據 GetProductsGetProductByProductIDGetProductsByCategoryIDGetProductBySuppliersID 的方法就相當簡單,因為它們只要呼叫 DAL 即可。 雖然在某些情況下,可能需要在此層級實作商務規則 (,例如根據目前登入的使用者或使用者所屬角色的授權規則,或使用者) 所屬的角色,我們只會依原狀保留這些方法。 針對這些方法,BLL 只會作為 Proxy,讓表示層從數據存取層存取基礎數據。

AddProductUpdateProduct 方法都會採用 作為各種產品欄位的值參數,並分別新增產品或更新現有的產品。 由於許多Product數據表的數據行都可以接受 NULL (CategoryIDSupplierIDUnitPrice的值,以命名幾個) ,因此,和 UpdateProduct 對應至這類數據行的輸入參數AddProduct會使用可為 Null 的類型。 可為 Null 的類型是 .NET 2.0 的新功能,並提供一種技術來指出實值型別是否應該是 null。 在 C# 中,您可以將實值型別標示為可為 Null 的類型,方法是在類型之後新增 ? (,例如 int? x;) 。 如需詳細資訊,請參閱 C# 程式設計手冊中的可為 Null 型別一節。

這三種方法都會傳回布爾值,指出數據列是否已插入、更新或刪除,因為作業可能不會造成受影響的數據列。 例如,如果頁面開發人員針對不存在的產品呼叫 DeleteProduct 傳入 ProductID ,則發出給資料庫的語句不會有任何影響, DELETE 因此 DeleteProduct 方法會傳回 false

請注意,在新增產品或更新現有產品時,我們會採用新的或修改產品域值作為純量清單,而不是接受 ProductsRow 實例。 因為類別衍生自沒有預設無參數建構函式的 DataRow ADO.NET 類別,因此已選擇ProductsRow此方法。 為了建立新的 ProductsRow 實例,我們必須先建立 ProductsDataTable 實例,然後叫用其 NewProductRow() 方法 (我們在) 中 AddProduct 執行。 當我們使用 ObjectDataSource 插入和更新產品時,這個缺點會重新上頭。 簡單來說,ObjectDataSource 會嘗試建立輸入參數的實例。 如果 BLL 方法需要 ProductsRow 實例,ObjectDataSource 會嘗試建立實例,但因為缺少預設無參數建構函式而失敗。 如需此問題的詳細資訊,請參閱下列兩個 ASP.NET 論壇文章: 使用 Strongly-Typed DataSet 更新 ObjectDataSources,以及 使用 ObjectDataSource 和 Strongly-Typed DataSet 的問題

接下來,在和 UpdateProductAddProduct,程式代碼會ProductsRow建立 實例,並填入剛傳入的值。 將值指派給 DataRow 各種欄位層級驗證檢查的 DataColumns 時,可能會發生。 因此,手動將傳入的值放回 DataRow 有助於確保傳遞至 BLL 方法的數據有效性。 不幸的是,Visual Studio 所產生的強型別 DataRow 類別不會使用可為 Null 的類型。 相反地,若要指出 DataRow 中的特定 DataColumn 應該對應至 NULL 必須使用 方法的資料庫 SetColumnNameNull() 值。

在 中 UpdateProduct ,我們會先載入產品,以使用 GetProductByProductID(productID)進行更新。 雖然這似乎是資料庫不必要的行程,但此額外行程在未來探索開放式並行存取的教學課程中將值得一提。 開放式並行存取是一種技術,可確保同時處理相同數據的兩位使用者不會不小心覆寫彼此的變更。 擷取整個記錄也可讓您更輕鬆地在 BLL 中建立只修改 DataRow 資料行子集的更新方法。 當我們探索類別時, SuppliersBLL 會看到這類範例。

最後,請注意,類別 ProductsBLL 已將 DataObject 屬性 套用至該屬性 ([System.ComponentModel.DataObject] 位於檔案頂端附近的類別語句之前) 語法,而且方法具有 DataObjectMethodAttribute 屬性。 屬性 DataObject 會將 類別標示為適合系結至 ObjectDataSource 控件的物件,而 DataObjectMethodAttribute 表示方法的用途。 如未來教學課程中所見,ASP.NET 2.0 的 ObjectDataSource 可讓您輕鬆地從類別宣告方式存取數據。 為了協助篩選在 ObjectDataSource 精靈中系結的可能類別清單,預設只會在精靈的下拉式清單中顯示標示為 DataObjects 的類別。 類別 ProductsBLL 的運作方式和沒有這些屬性一樣,但新增它們可讓您更輕鬆地在 ObjectDataSource 的精靈中使用。

新增其他類別

完成類別 ProductsBLL 之後,我們仍然需要新增類別,以使用類別、供應商和員工。 請花點時間使用上述範例的概念來建立下列類別和方法:

  • 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 方法。 這個方法提供介面,只更新供應商的地址資訊。 在內部,這個方法SupplierDataRow會使用 GetSupplierBySupplierID) 讀取指定supplierID之 (的對象、設定其位址相關屬性,然後向下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)
        // no matching record found, return 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;

        // Update the supplier Address-related information
        int rowsAffected = Adapter.Update(supplier);

        // Return true if precisely one row was updated,
        // otherwise false
        return rowsAffected == 1;
    }
}

如需 BLL 類別的完整實作,請參閱本文的下載。

步驟 2:透過 BLL 類別存取具類型的數據集

在第一個教學課程中,我們看到直接以程序設計方式使用具型別數據集的範例,但透過新增 BLL 類別,表示層應該改為針對 BLL 運作。 在第一個教學課程的 AllProducts.aspx 範例中, ProductsTableAdapter 用來將產品清單系結至 GridView,如下列程式代碼所示:

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

若要使用新的 BLL 類別,所有需要變更的專案都是第一行程式代碼,只要將 ProductsTableAdapter 物件取代為 ProductBLL 物件:

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

BLL 類別也可以以宣告方式存取 (,如同使用 ObjectDataSource) Typed DataSet。 我們將在下列教學課程中更詳細地討論 ObjectDataSource。

產品清單會顯示在 GridView 中

圖 3:產品清單會顯示在 GridView (按鍵即可檢視全尺寸影像)

步驟 3:將 Field-Level 驗證新增至 DataRow 類別

欄位層級驗證會在插入或更新時,檢查與商務對象的屬性值有關。 產品的一些欄位層級驗證規則包括:

  • 欄位 ProductName 長度必須為 40 個字元或更少
  • 欄位 QuantityPerUnit 長度必須為 20 個字元或更少
  • ProductIDProductNameDiscontinued 欄位是必要的,但所有其他欄位都是選擇性的
  • UnitPriceUnitsInStockUnitsOnOrderReorderLevel 欄位必須大於或等於零

這些規則可以且應該以資料庫層級表示。 和欄位的ProductName字元限制會分別由數據表中的數據Products行數據類型擷取 (nvarchar(40)nvarchar(20)) 。QuantityPerUnit 如果資料庫數據表數據行允許 NULL ,則是否為必要欄位和選擇性欄位。 存在四個 檢查條件約束 ,以確保只有大於或等於零的值可以讓它成為 UnitPriceUnitsInStockUnitsOnOrder或 數據 ReorderLevel 行。

除了在資料庫強制執行這些規則之外,也應該在 DataSet 層級強制執行這些規則。 事實上,欄位長度以及每個 DataTable 的 DataColumns 集合都已經擷取值或選擇性值。 若要查看自動提供的現有欄位層級驗證,請移至 DataSet Designer,從其中一個 DataTable 中選取字段,然後移至 屬性視窗。 如圖 4 所示, QuantityPerUnit 中的 ProductsDataTable DataColumn 長度上限為 20 個字元,而且允許 NULL 值。 如果我們嘗試將 ProductsDataRow的 屬性設定為超過 20 個字元ArgumentExceptionQuantityPerUnit字串值,將會擲回 。

DataColumn 提供基本 Field-Level 驗證

圖 4:D ataColumn 提供基本 Field-Level 驗證 (按兩下即可檢視完整大小的映像)

可惜的是,我們無法透過 屬性視窗 指定界限檢查,例如UnitPrice值必須大於或等於零。 為了提供這種類型的欄位層級驗證,我們需要為 DataTable 的 ColumnChanging 事件建立事件處理程式。 如上一個 教學課程所述,DataSet、DataTables 和 Typed DataSet 所建立的 DataRow 物件可以透過使用部分類別來擴充。 使用這項技術,我們可以建立 ColumnChanging 類別的 ProductsDataTable 事件處理程式。 首先,在名為ProductsDataTable.ColumnChanging.csApp_Code資料夾中建立類別。

將新類別新增至 App_Code資料夾

圖 5:將新類別新增至 App_Code 資料夾 (按兩下以檢視大小完整的影像)

接下來,建立 ColumnChanging 事件的事件處理程式,以確保UnitPrice如果 NULL) 大於或等於零,則 (、 UnitsInStockUnitsOnOrderReorderLevel 數據行值。 如果有任何這類資料行超出範圍,請擲回 ArgumentException

ProductsDataTable.ColumnChanging.cs

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

步驟 4:將自定義商務規則新增至 BLL 的類別

除了欄位層級驗證之外,可能有高階自定義商務規則牽涉到單一數據行層級無法表達的不同實體或概念,例如:

  • 如果產品已停止,則無法更新產品UnitPrice
  • 員工的居住國家/地區必須與其主管的居住國家/地區相同
  • 如果產品是唯一由供應商提供的產品,則無法停止產品

BLL 類別應該包含檢查,以確保遵守應用程式的商務規則。 這些檢查可以直接新增至套用的方法。

假設我們的商務規則規定,如果產品是唯一來自指定供應商的產品,則無法將其標示為已停止。 也就是說,如果 product X 是唯一從供貨商 Y 購買的產品,則無法將 X 標示為已停止;不過,如果供應商 Y 提供三個產品 ABC,我們可以將上述任何和所有項目標示為已停止。 奇數商務規則,但商務規則和常見意義不一定一致!

若要在我們開始檢查是否已Discontinued設定true為 的方法中UpdateProducts強制執行此商務規則,若是如此,我們會呼叫 GetProductsBySupplierID 來判斷我們從本產品供應商購買的產品數目。 如果只從此供應商購買一個產品,我們會擲回 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)
        // no matching record found, return false
        return false;

    Northwind.ProductsRow product = products[0];

    // Business rule check - cannot discontinue
    // a product that is supplied by only
    // one supplier
    if (discontinued)
    {
        // Get the products we buy from this supplier
        Northwind.ProductsDataTable productsBySupplier =
            Adapter.GetProductsBySupplierID(product.SupplierID);

        if (productsBySupplier.Count == 1)
            // this is the only product we buy from this supplier
            throw new ApplicationException(
                "You cannot mark a product as discontinued if it is 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;

    // Update the product record
    int rowsAffected = Adapter.Update(product);

    // Return true if precisely one row was updated,
    // otherwise false
    return rowsAffected == 1;
}

回應呈現層中的驗證錯誤

從呈現層呼叫 BLL 時,我們可以決定是否嘗試處理任何可能引發的例外狀況,或讓它們反升為 ASP.NET (,這會引發 HttpApplication的事件 Error) 。 若要以程式設計方式處理 BLL 時發生例外狀況,我們可以 嘗試...catch 區塊,如下列範例所示:

ProductsBLL productLogic = new ProductsBLL();

// Update information for ProductID 1
try
{
    // This will fail since we are attempting to use a
    // UnitPrice value less than 0.
    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);
}

如未來教學課程所示,使用數據 Web 控制件插入、更新或刪除資料時,處理從 BLL 升空的例外狀況,可以直接在事件處理程式中處理,而不需要將程式代碼包裝在區塊中 try...catch

摘要

妥善架構的應用程式會製作成不同的層級,每個層都會封裝特定的角色。 在本文章系列的第一個教學課程中,我們使用具型別數據集建立數據存取層;在本教學課程中,我們將商業規則層建置為應用程式 App_Code 資料夾中可呼叫 DAL 的一系列類別。 BLL 會實作應用程式的欄位層級和商業層級邏輯。 除了建立個別的 BLL 之外,如同在本教學課程中所做的一樣,另一個選項是透過使用部分類別來擴充 TableAdapters 的方法。 不過,使用此技術不允許我們覆寫現有的方法,也不會像本文中所採用的方法一樣清楚地分隔 DAL 和 BLL。

完成 DAL 和 BLL 之後,我們就可以開始呈現層。 在下 一個教學課程 中,我們將從數據存取主題取得簡短的導覽,並定義一致的頁面配置,以在整個教學課程中使用。

快樂的程序設計!

關於作者

Scott Mitchell 是七份 ASP/ASP.NET 書籍的作者,以及 1998 年以來與 Microsoft Web 技術合作的 4GuysFromRolla.com 作者。 Scott 是獨立顧問、訓練員和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格來連線到 ,您可以在 找到http://ScottOnWriting.NET

特別感謝

本教學課程系列是由許多實用的檢閱者檢閱。 本教學課程的首席檢閱者是 Liz Shulok、Dennis Patterson、Carlos 擷取者及克羅吉斯enow。 有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。