共用方式為


建立商業邏輯層 (VB)

作者 :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 資料夾中建立兩個子資料夾, DAL 以及 BLL。 只要以滑鼠右鍵按兩下 App_Code 方案總管中的資料夾,然後選擇[新增資料夾]。 建立這兩個資料夾之後,請將第一個 DAL 教學課程中建立的具類型數據集移至子資料夾。

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

將四個新類別新增至 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.vb

Imports NorthwindTableAdapters

<System.ComponentModel.DataObject()> _
Public Class ProductsBLL

    Private _productsAdapter As ProductsTableAdapter = Nothing
    Protected ReadOnly Property Adapter() As ProductsTableAdapter
        Get
            If _productsAdapter Is Nothing Then
                _productsAdapter = New ProductsTableAdapter()
            End If

            Return _productsAdapter
        End Get
    End Property

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Select, True)> _
    Public Function GetProducts() As Northwind.ProductsDataTable
        Return Adapter.GetProducts()
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Select, False)> _
    Public Function GetProductByProductID(ByVal productID As Integer) _
        As Northwind.ProductsDataTable
        Return Adapter.GetProductByProductID(productID)
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Select, False)> _
    Public Function GetProductsByCategoryID(ByVal categoryID As Integer) _
        As Northwind.ProductsDataTable
        Return Adapter.GetProductsByCategoryID(categoryID)
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Select, False)> _
    Public Function GetProductsBySupplierID(ByVal supplierID As Integer) _
        As Northwind.ProductsDataTable
        Return Adapter.GetProductsBySupplierID(supplierID)
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Insert, True)> _
    Public Function AddProduct( _
        productName As String, supplierID As Nullable(Of Integer), _
        categoryID As Nullable(Of Integer), quantityPerUnit As String, _
        unitPrice As Nullable(Of Decimal), unitsInStock As Nullable(Of Short), _
        unitsOnOrder As Nullable(Of Short), reorderLevel As Nullable(Of Short), _
        discontinued As Boolean) _
        As Boolean

        Dim products As New Northwind.ProductsDataTable()
        Dim product As Northwind.ProductsRow = products.NewProductsRow()

        product.ProductName = productName
        If Not supplierID.HasValue Then
            product.SetSupplierIDNull()
        Else
            product.SupplierID = supplierID.Value
        End If

        If Not categoryID.HasValue Then
            product.SetCategoryIDNull()
        Else
            product.CategoryID = categoryID.Value
        End If

        If quantityPerUnit Is Nothing Then
            product.SetQuantityPerUnitNull()
        Else
            product.QuantityPerUnit = quantityPerUnit
        End If

        If Not unitPrice.HasValue Then
            product.SetUnitPriceNull()
        Else
            product.UnitPrice = unitPrice.Value
        End If

        If Not unitsInStock.HasValue Then
            product.SetUnitsInStockNull()
        Else
            product.UnitsInStock = unitsInStock.Value
        End If

        If Not unitsOnOrder.HasValue Then
            product.SetUnitsOnOrderNull()
        Else
            product.UnitsOnOrder = unitsOnOrder.Value
        End If

        If Not reorderLevel.HasValue Then
            product.SetReorderLevelNull()
        Else
            product.ReorderLevel = reorderLevel.Value
        End If

        product.Discontinued = discontinued

        products.AddProductsRow(product)
        Dim rowsAffected As Integer = Adapter.Update(products)

        Return rowsAffected = 1
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Update, True)> _
    Public Function UpdateProduct(_
        productName As String, supplierID As Nullable(Of Integer), _
        categoryID As Nullable(Of Integer), quantityPerUnit As String, _
        unitPrice As Nullable(Of Decimal), unitsInStock As Nullable(Of Short), _
        unitsOnOrder As Nullable(Of Short), reorderLevel As Nullable(Of Short), _
        discontinued As Boolean, productID As Integer) _
        As Boolean

        Dim products As Northwind.ProductsDataTable = _
            Adapter.GetProductByProductID(productID)

        If products.Count = 0 Then
            Return False
        End If

        Dim product as Northwind.ProductsRow = products(0)

        product.ProductName = productName
        If Not supplierID.HasValue Then
            product.SetSupplierIDNull()
        Else
            product.SupplierID = supplierID.Value
        End If

        If Not categoryID.HasValue Then
            product.SetCategoryIDNull()
        Else
            product.CategoryID = categoryID.Value
        End If

        If quantityPerUnit Is Nothing Then
            product.SetQuantityPerUnitNull()
        Else
            product.QuantityPerUnit = quantityPerUnit
        End If

        If Not unitPrice.HasValue Then
            product.SetUnitPriceNull()
        Else
            product.UnitPrice = unitPrice.Value
        End If

        If Not unitsInStock.HasValue Then
            product.SetUnitsInStockNull()
        Else
            product.UnitsInStock = unitsInStock.Value
        End If

        If Not unitsOnOrder.HasValue Then
            product.SetUnitsOnOrderNull()
        Else
            product.UnitsOnOrder = unitsOnOrder.Value
        End If

        If Not reorderLevel.HasValue Then
            product.SetReorderLevelNull()
        Else
            product.ReorderLevel = reorderLevel.Value
        End If

        product.Discontinued = discontinued

        Dim rowsAffected As Integer = Adapter.Update(product)

        Return rowsAffected = 1
    End Function

    <System.ComponentModel.DataObjectMethodAttribute _
        (System.ComponentModel.DataObjectMethodType.Delete, True)> _
    Public Function DeleteProduct(ByVal productID As Integer) As Boolean
        Dim rowsAffected As Integer = Adapter.Delete(productID)

        Return rowsAffected = 1
    End Function
End Class

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

AddProductUpdateProduct 方法都會以參數的形式採用各種產品欄位的值,並分別新增產品或更新現有的產品。 由於許多Product數據表的數據行都可以接受 NULL (CategoryIDSupplierIDUnitPrice的值來命名幾個) ,因此UpdateProduct和 對應至這類數據行的輸入參數AddProduct會使用可為 Null 的類型。 可為 Null 的型別是 .NET 2.0 的新功能,並提供技術來指出實值型別是否應改為為 Nothing。 如需詳細資訊,請參閱 Paul Vick 的部落格文章 :關於可為 Null 的類型和 VB 的真 人,以及 可為 Null 結構的技術檔。

這三種方法都會傳回 Boolean 值,指出數據列是否已插入、更新或刪除,因為作業可能不會造成受影響的數據列。 例如,如果頁面開發人員針對不存在的產品呼叫 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 和 ObjectDataSourceStrongly-Typed DataSet 的問題

接下來,在 AddProductUpdateProduct中,程式代碼會 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 Function UpdateSupplierAddress(ByVal supplierID As Integer, _
    ByVal address As String, ByVal city As String, ByVal country As String) _
    As Boolean

    Dim suppliers As Northwind.SuppliersDataTable = _
        Adapter.GetSupplierBySupplierID(supplierID)

    If suppliers.Count = 0 Then
        Return False
    Else
        Dim supplier As Northwind.SuppliersRow = suppliers(0)

        If address Is Nothing Then
            supplier.SetAddressNull()
        Else
            supplier.Address = address
        End If

        If city Is Nothing Then
            supplier.SetCityNull()
        Else
            supplier.City = city
        End If

        If country Is Nothing Then
            supplier.SetCountryNull()
        Else
            supplier.Country = country
        End If

        Dim rowsAffected As Integer = Adapter.Update(supplier)

        Return rowsAffected = 1
    End If
End Function

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

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

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

Dim productsAdapter As New ProductsTableAdapter()
GridView1.DataSource = productsAdapter.GetProducts()
GridView1.DataBind()

若要使用新的 BLL 類別,只需要變更第一行程式代碼,只要將 ProductsTableAdapter 物件取代為 ProductBLL 物件即可:

Dim productLogic As 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 ,則字段是否為必要和選擇性的表示方式。 存在四個 檢查條件約束 ,以確保只有大於或等於零的值可以讓它成為 UnitPriceUnitsInStockUnitsOnOrderReorderLevel 數據行。

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

DataColumn 提供基本 Field-Level 驗證

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

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

將新類別新增至 App_Code資料夾

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

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

ProductsDataTable.ColumnChanging.vb

Imports System.data

Partial Public Class Northwind
    Partial Public Class ProductsDataTable
        Public Overrides Sub BeginInit()
            AddHandler Me.ColumnChanging, AddressOf ValidateColumn
        End Sub

        Sub ValidateColumn(sender As Object, e As DataColumnChangeEventArgs)
            If e.Column.Equals(Me.UnitPriceColumn) Then
                If Not Convert.IsDBNull(e.ProposedValue) AndAlso _
                    CType(e.ProposedValue, Decimal) < 0 Then
                    Throw New ArgumentException( _
                        "UnitPrice cannot be less than zero", "UnitPrice")
                End If
            ElseIf e.Column.Equals(Me.UnitsInStockColumn) OrElse _
                e.Column.Equals(Me.UnitsOnOrderColumn) OrElse _
                e.Column.Equals(Me.ReorderLevelColumn) Then
                If Not Convert.IsDBNull(e.ProposedValue) AndAlso _
                    CType(e.ProposedValue, Short) < 0 Then
                    Throw New ArgumentException(String.Format( _
                        "{0} cannot be less than zero", e.Column.ColumnName), _
                        e.Column.ColumnName)
                End If
            End If
        End Sub
    End Class
End Class

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

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

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

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

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

為了在方法中 UpdateProducts 強制執行此商務規則,我們會先檢查是否已 Discontinued 設定為 True ,如果是的話,我們會呼叫 GetProductsBySupplierID 來判斷我們從本產品供應商購買的產品數量。 如果此供應商只購買一項產品,我們會擲回 ApplicationException

<System.ComponentModel.DataObjectMethodAttribute_
    (System.ComponentModel.DataObjectMethodType.Update, True)> _
Public Function UpdateProduct( _
    productName As String, supplierID As Nullable(Of Integer), _
    categoryID As Nullable(Of Integer), quantityPerUnit As String, _
    unitPrice As Nullable(Of Decimal), unitsInStock As Nullable(Of Short), _
    unitsOnOrder As Nullable(Of Short), reorderLevel As Nullable(Of Short), _
    discontinued As Boolean, productID As Integer) _
    As Boolean

    Dim products As Northwind.ProductsDataTable = _
        Adapter.GetProductByProductID(productID)

    If products.Count = 0 Then
        Return False
    End If

    Dim product As Northwind.ProductsRow = products(0)

    If discontinued Then
        Dim productsBySupplier As Northwind.ProductsDataTable = _
            Adapter.GetProductsBySupplierID(product.SupplierID)

        If productsBySupplier.Count = 1 Then
            Throw New ApplicationException( _
                "You cannot mark a product as discontinued if it is " & _
                "the only product purchased from a supplier")
        End If
    End If

    product.ProductName = productName

    If Not supplierID.HasValue Then
        product.SetSupplierIDNull()
    Else
        product.SupplierID = supplierID.Value
    End If

    If Not categoryID.HasValue Then
        product.SetCategoryIDNull()
    Else
        product.CategoryID = categoryID.Value
    End If

    If quantityPerUnit Is Nothing Then
        product.SetQuantityPerUnitNull()
    Else
        product.QuantityPerUnit = quantityPerUnit
    End If

    If Not unitPrice.HasValue Then
        product.SetUnitPriceNull()
    Else
        product.UnitPrice = unitPrice.Value
    End If

    If Not unitsInStock.HasValue Then
        product.SetUnitsInStockNull()
    Else
        product.UnitsInStock = unitsInStock.Value
    End If

    If Not unitsOnOrder.HasValue Then
        product.SetUnitsOnOrderNull()
    Else
        product.UnitsOnOrder = unitsOnOrder.Value
    End If

    If Not reorderLevel.HasValue Then
        product.SetReorderLevelNull()
    Else
        product.ReorderLevel = reorderLevel.Value
    End If

    product.Discontinued = discontinued

    Dim rowsAffected As Integer = Adapter.Update(product)

    Return rowsAffected = 1
End Function

回應表示層中的驗證錯誤

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

Dim productLogic As New ProductsBLL()

Try
    productLogic.UpdateProduct("Scotts Tea", 1, 1, Nothing, _
      -14, 10, Nothing, Nothing, False, 1)
Catch ae As ArgumentException
    Response.Write("There was a problem: " & ae.Message)
End Try

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

摘要

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

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

快樂的程序設計!

關於作者

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

特別感謝

本教學課程系列是由許多實用的檢閱者所檢閱。 本教學課程的首席檢閱者是 Liz Shulok、Dennis Patterson、Carlos 一文和卡洛西尼亞文。 想要檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com。