Aracılığıyla paylaş


İş Mantığı Katmanı Oluşturma (VB)

tarafından Scott Mitchell

PDF'i indirin

Bu eğitimde, iş kurallarınızı sunum katmanı ile DAL arasında veri alışverişi için aracı görevi gören bir İş Mantığı Katmanı'nda (BLL) nasıl merkezileştireceğinizi göreceğiz.

Giriş

İlk öğreticide oluşturulan Veri Erişim Katmanı (DAL), veri erişim mantığını sunu mantığından temiz bir şekilde ayırır. Bununla birlikte, DAL, veri erişim ayrıntılarını sunum katmanından temiz bir şekilde ayırırken, geçerli olabilecek herhangi bir iş kuralını uygulamaz. Örneğin, uygulamamız için, alan 1 olarak ayarlandığında CategoryID tablonun SupplierID veya Products alanlarının değiştirilmesine izin Discontinued vermemek isteyebiliriz veya bir çalışanın kendisinden sonra işe alınan biri tarafından yönetildiği durumları yasaklayarak kıdem kurallarını uygulamak isteyebiliriz. Diğer bir yaygın senaryo yetkilendirmedir, belki de yalnızca belirli bir roldeki kullanıcılar ürünleri silebilir veya değeri değiştirebilir UnitPrice .

Bu öğreticide, bu iş kurallarının, sunum katmanı ile DAL arasında veri alışverişi için aracı görevi gören bir İş Mantığı Katmanı'nda (BLL) nasıl merkezileştirileceğini göreceğiz. Gerçek dünyadaki bir uygulamada, BLL ayrı bir Sınıf Kitaplığı projesi olarak uygulanmalıdır; ancak, bu öğreticiler için proje yapısını basitleştirmek için BLL'yi klasörümüzde App_Code bir dizi sınıf olarak uygulayacağız. Şekil 1, sunum katmanı, BLL ve DAL arasındaki mimari ilişkileri göstermektedir.

BLL, Sunum Katmanını Veri Erişim Katmanından Ayırır ve İş Kurallarını Uygular

Şekil 1: BLL, Sunum Katmanını Veri Erişim Katmanından Ayırır ve İş Kurallarını Uygular

İş mantığımızı uygulamak için ayrı sınıflar oluşturmak yerine, alternatif olarak bu mantığı kısmi sınıflarla doğrudan Typed DataSet'e yerleştirebiliriz. Yazılan Veri Kümesi oluşturma ve genişletme örneği için ilk öğreticiye geri dönün.

Adım 1: BLL Sınıflarını Oluşturma

BLL'miz, DAL'daki her TableAdapter için bir tane olmak üzere dört sınıftan oluşacaktır; Bu BLL sınıflarının her biri, uygun iş kurallarını uygulayarak DAL'deki ilgili TableAdapter'dan alma, ekleme, güncelleştirme ve silme yöntemlerine sahip olacaktır.

DAL ve BLL ile ilgili sınıfları daha temiz bir şekilde ayırmak için, klasörde App_CodeDAL iki alt klasör oluşturalım ve BLL. Çözüm Gezgini'nde klasöre sağ tıklayın App_Code ve Yeni Klasör'ü seçin. Bu iki klasörü oluşturduktan sonra, ilk öğreticide oluşturulan Yazılan Veri Kümesi'ni DAL alt klasöre taşıyın.

Ardından, alt klasörde BLL dört BLL sınıf dosyasını oluşturun. Bunu gerçekleştirmek için alt klasöre sağ tıklayın BLL , Yeni Öğe Ekle'yi seçin ve Sınıf şablonunu seçin. Dört sınıfı ProductsBLL, CategoriesBLL, SuppliersBLLve EmployeesBLLolarak adlandırın.

App_Code klasörüne dört yeni sınıf ekleme

Şekil 2: Klasöre dört yeni sınıf App_Code ekleme

Ardından, ilk öğreticiden TableAdapters için tanımlanan yöntemleri basitçe sarmalamak için sınıfların her birine yöntemler ekleyelim. Şimdilik, bu yöntemler doğrudan DAL'ı arayacak; Gerekli iş mantığını eklemek için daha sonra geri döneceğiz.

Uyarı

Visual Studio Standard Edition veya üzerini kullanıyorsanız (diğer bir deyişle, Visual Web Developer kullanmıyorsanız ), isteğe bağlı olarak Sınıf Tasarımcısı'nı kullanarak sınıflarınızı görsel olarak tasarlayabilirsiniz. Visual Studio'daki bu yeni özellik hakkında daha fazla bilgi için Sınıf Tasarımcısı Blogu'na bakın.

ProductsBLL Sınıf için toplam yedi yöntem eklememiz gerekiyor:

  • GetProducts() Tüm ürünleri iade eder
  • GetProductByProductID(productID) Belirtilen ürün kimliğine sahip ürünü iade eder
  • GetProductsByCategoryID(categoryID) Belirtilen kategorideki tüm ürünleri döndürür
  • GetProductsBySupplier(supplierID) Belirtilen tedarikçiden gelen tüm ürünleri iade eder
  • AddProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued) iletilen değerleri kullanarak veritabanına yeni bir ürün ekler; ProductID Yeni eklenen kaydın değerini döndürür
  • UpdateProduct(productName, supplierID, categoryID, quantityPerUnit, unitPrice, unitsInStock, unitsOnOrder, reorderLevel, discontinued, productID) iletilen değerleri kullanarak veritabanındaki mevcut bir ürünü günceller; tam olarak bir satır güncellenmişse döndürür True , False aksi takdirde
  • DeleteProduct(productID) Belirtilen ürünü veritabanından siler

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

Basitçe veri GetProductsdöndüren yöntemler , GetProductByProductID, GetProductsByCategoryIDve GetProductBySuppliersID basitçe DAL'a çağrıldıkları için oldukça basittir. Bazı senaryolarda bu düzeyde uygulanması gereken iş kuralları olsa da (şu anda oturum açmış olan kullanıcıyı veya kullanıcının ait olduğu rolü temel alan yetkilendirme kuralları gibi), bu yöntemleri as-isbırakacağız. Bu yöntemler için, BLL, yalnızca sunum katmanının Veri Erişim Katmanı'ndan temel alınan verilere eriştiği bir proxy görevi görür.

ve AddProductUpdateProduct yöntemlerinin her ikisi de çeşitli ürün alanlarının değerlerini parametre olarak alır ve sırasıyla yeni bir ürün ekler veya mevcut bir ürünü günceller. Tablonun Product sütunlarının çoğu (NULL, CategoryIDve SupplierID, birkaç ad) değerlerini kabul UnitPrice edebildiğinden, bu tür sütunlar için AddProduct ve UpdateProduct bu tür sütunlarla eşlenen giriş parametreleri null atanabilir türler kullanır. Null atanabilir türler .NET 2.0'da yenidir ve bunun yerine bir değer türünün olması Nothinggerekip gerekmediğini belirtmek için bir teknik sağlar. Daha fazla bilgi için Paul Vick'inThe Truth About Nullable Types and VB adlı blog girişine ve Nullable yapısının teknik belgelerine bakın.

Her üç yöntem de bir satırın eklendiğini, güncelleştirildiğini veya silindiğini belirten bir Boole değeri döndürür, çünkü işlem etkilenen bir satırla sonuçlanmayabilir. Örneğin, sayfa geliştiricisi var olmayan bir ürün için a geçirme çağrısı DeleteProduct yaparsa, veritabanına verilen ifadenin ProductID hiçbir etkisi olmaz ve bu nedenle DELETE yöntem döndürürDeleteProduct.False

Yeni bir ürün eklerken veya mevcut bir ürünü güncellerken, bir örneği kabul ProductsRow etmek yerine, yeni veya değiştirilmiş ürünün alan değerlerini skaler listesi olarak aldığımızı unutmayın. Bu yaklaşım, sınıfın varsayılan parametresiz oluşturucusu olmayan ADO.NET ProductsRow sınıfından türetilmesi nedeniyle seçilmiştirDataRow. Yeni ProductsRow bir örnek oluşturmak için önce bir ProductsDataTable örnek oluşturmalı ve ardından yöntemini NewProductRow() çağırmalıyız (ki bunu içinde AddProductyaparız). Bu eksiklik, ObjectDataSource kullanarak ürün eklemeye ve güncellemeye döndüğümüzde başını kaldırıyor. Kısacası, ObjectDataSource giriş parametrelerinin bir örneğini oluşturmaya çalışacaktır. BLL yöntemi bir ProductsRow örnek bekliyorsa, ObjectDataSource bir örnek oluşturmayı dener, ancak varsayılan parametresiz oluşturucunun olmaması nedeniyle başarısız olur. Bu sorun hakkında daha fazla bilgi için, aşağıdaki iki ASP.NET Forumu gönderisine bakın: ObjectDataSources'ı Strongly-Typed DataSets ile Güncelleştirme ve ObjectDataSource ve Strongly-Typed DataSet ile İlgili Sorun.

Ardından, her ikisinde de AddProduct ve UpdateProductkod bir ProductsRow örnek oluşturur ve bunu az önce geçirilen değerlerle doldurur. Bir DataRow'un DataColumns'una değer atarken, çeşitli alan düzeyinde doğrulama denetimleri oluşabilir. Bu nedenle, geçirilen değerleri bir DataRow'a el ile geri koymak, BLL yöntemine geçirilen verilerin geçerliliğini sağlamaya yardımcı olur. Ne yazık ki, Visual Studio tarafından oluşturulan kesin olarak belirlenmiş DataRow sınıfları null atanabilir türler kullanmaz. Bunun yerine, bir DataRow içindeki belirli bir DataColumn'un bir NULL veritabanı değerine karşılık gelmesi gerektiğini belirtmek için yöntemi kullanmamız SetColumnNameNull() gerekir.

Önce UpdateProduct kullanarak güncellemek GetProductByProductID(productID)için ürünü yüklüyoruz. Bu, veritabanına gereksiz bir yolculuk gibi görünse de, bu ekstra yolculuk, iyimser eşzamanlılığı araştıran gelecekteki öğreticilerde faydalı olacaktır. İyimser eşzamanlılık, aynı veriler üzerinde aynı anda çalışan iki kullanıcının yanlışlıkla birbirlerinin değişikliklerinin üzerine yazmamasını sağlamak için kullanılan bir tekniktir. Kaydın tamamını almak, BLL'de DataRow sütunlarının yalnızca bir alt kümesini değiştiren güncelleştirme yöntemleri oluşturmayı da kolaylaştırır. Sınıfı incelediğimizde SuppliersBLL böyle bir örnek göreceğiz.

Son olarak, sınıfa ProductsBLLDataObject özniteliğinin uygulandığını ( [System.ComponentModel.DataObject] dosyanın üst kısmına yakın bir yerde sınıf deyiminden hemen önceki sözdizimi) ve yöntemlerin DataObjectMethodAttribute özniteliklerine sahip olduğunu unutmayın. Özniteliği DataObject , sınıfı bir ObjectDataSource denetimine bağlanmaya uygun bir nesne olarak işaretlerken, yöntem DataObjectMethodAttribute amacını belirtir. Gelecekteki öğreticilerde göreceğimiz gibi, ASP.NET 2.0'ın ObjectDataSource'u bir sınıftan verilere bildirimli olarak erişmeyi kolaylaştırır. ObjectDataSource sihirbazında bağlanacak olası sınıfların listesini filtrelemeye yardımcı olmak için, varsayılan olarak sihirbazın açılan listesinde yalnızca olarak DataObjects işaretlenen sınıflar gösterilir. Sınıf ProductsBLL , bu öznitelikler olmadan da iyi çalışır, ancak bunları eklemek ObjectDataSource sihirbazında çalışmayı kolaylaştırır.

Diğer Sınıfları Ekleme

ProductsBLL Sınıf tamamlandıktan sonra, kategoriler, tedarikçiler ve çalışanlarla çalışmak için sınıfları eklememiz gerekiyor. Yukarıdaki örnekte yer alan kavramları kullanarak aşağıdaki sınıfları ve yöntemleri oluşturmak için biraz zaman ayırın:

  • CategoriesBLL.cs

    • GetCategories()
    • GetCategoryByCategoryID(categoryID)
  • SuppliersBLL.cs

    • GetSuppliers()
    • GetSupplierBySupplierID(supplierID)
    • GetSuppliersByCountry(country)
    • UpdateSupplierAddress(supplierID, address, city, country)
  • EmployeesBLL.cs

    • GetEmployees()
    • GetEmployeeByEmployeeID(employeeID)
    • GetEmployeesByManager(managerID)

Kayda değer bir yöntem, sınıfın SuppliersBLLUpdateSupplierAddress yöntemidir. Bu yöntem, yalnızca tedarikçinin adres bilgilerini güncellemek için bir arabirim sağlar. Dahili olarak, bu yöntem belirtilen (kullanarakSupplierDataRow) için nesneyi okursupplierID, adresle ilgili özelliklerini ayarlar ve ardından ' GetSupplierBySupplierID yöntemine çağırırSupplierDataTable.Update Yöntem UpdateSupplierAddress aşağıdaki gibidir:

<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 sınıflarının tam uygulaması için bu makalenin indirilmesine bakın.

Adım 2: BLL sınıfları aracılığıyla yazılan DataSets'e erişme

İlk öğreticide, Yazılan Veri Kümesi ile programlı olarak doğrudan çalışma örneklerini gördük, ancak BLL sınıflarımızın eklenmesiyle, sunum katmanı bunun yerine BLL'ye karşı çalışmalıdır. AllProducts.aspx İlk öğreticideki örnekte, ProductsTableAdapter aşağıdaki kodda gösterildiği gibi ürün listesini bir GridView'a bağlamak için kullanılmıştır:

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

Yeni BLL sınıflarını kullanmak için değiştirilmesi gereken tek şey kodun ilk satırının nesneyi bir ProductsTableAdapter nesneyle değiştirmesidirProductBLL:

Dim productLogic As New ProductsBLL()
GridView1.DataSource = productLogic.GetProducts()
GridView1.DataBind()

BLL sınıflarına ObjectDataSource kullanılarak bildirimli olarak da erişilebilir (Typed DataSet gibi). Aşağıdaki öğreticilerde ObjectDataSource'u daha ayrıntılı olarak tartışacağız.

Ürün Listesi GridView'da Görüntülenir

Şekil 3: Ürün Listesi Bir GridView'da Görüntüleniyor (Tam boyutlu görüntüyü görüntülemek için tıklayın)

3. Adım: DataRow Sınıflarına Field-Level Doğrulama Ekleme

Alan düzeyinde doğrulama, ekleme veya güncelleme sırasında iş nesnelerinin özellik değerleriyle ilgili denetimlerdir. Ürünler için bazı alan düzeyinde doğrulama kuralları şunları içerir:

  • Alanın ProductName uzunluğu 40 karakter veya daha az olmalıdır
  • Alan QuantityPerUnit 20 karakter veya daha kısa olmalıdır
  • ProductID, ProductName, ve Discontinued alanları gereklidir, ancak diğer tüm alanlar isteğe bağlıdır
  • , UnitPriceUnitsInStock, UnitsOnOrder, ve ReorderLevel alanları sıfırdan büyük veya sıfıra eşit olmalıdır

Bu kurallar veritabanı düzeyinde ifade edilebilir ve ifade edilmelidir. ve ProductName alanlarındaki karakter sınırıQuantityPerUnit, tablodaki bu sütunların veri türleri tarafından yakalanır (Products ve nvarchar(40)sırasıylanvarchar(20)). Alanların gerekli ve isteğe bağlı olup olmadığı, veritabanı tablo sütununun s'ye izin verip vermediği NULL ile ifade edilir. Yalnızca sıfırdan büyük veya sıfıra eşit değerlerin , , UnitPriceveya UnitsInStock sütunlarına girebilmesini sağlayan dört UnitsOnOrderReorderLevelvardır.

Bu kuralları veritabanında zorlamanın yanı sıra, DataSet düzeyinde de uygulanmaları gerekir. Aslında, alan uzunluğu ve bir değerin gerekli mi yoksa isteğe bağlı mı olduğu her DataTable'ın DataColumns kümesi için zaten yakalanmıştır. Otomatik olarak sağlanan mevcut alan düzeyi doğrulamayı görmek için DataSet Designer'a gidin, DataTable'lardan birinden bir alan seçin ve ardından Özellikler penceresine gidin. Şekil 4'te gösterildiği gibi, QuantityPerUnit içindeki ProductsDataTable DataColumn en fazla 20 karakter uzunluğuna sahiptir ve değerlere izin verir NULL . ' ProductsDataRow özelliğini 20 karakterden daha uzun bir dize değerine ayarlamaya QuantityPerUnitçalışırsak, bir ArgumentException oluşturulur.

DataColumn, temel Field-Level doğrulaması sağlar

Şekil 4: DataColumn Temel Field-Level Doğrulaması Sağlar (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Ne yazık ki, Özellikler penceresi aracılığıyla değerin UnitPrice sıfırdan büyük veya sıfıra eşit olması gerektiği gibi sınır denetimlerini belirtemiyoruz. Bu tür bir alan düzeyinde doğrulama sağlamak için, DataTable'ın ColumnChanging olayı için bir olay işleyicisi oluşturmamız gerekir. Önceki öğreticide belirtildiği gibi, Typed DataSet tarafından oluşturulan DataSet, DataTables ve DataRow nesneleri kısmi sınıflar kullanılarak genişletilebilir. Bu tekniği kullanarak sınıf için bir ColumnChanging olay işleyicisi ProductsDataTable oluşturabiliriz. adlı klasörde App_CodeProductsDataTable.ColumnChanging.vbbir sınıf oluşturarak başlayın.

App_Code klasörüne yeni bir sınıf ekleme

Şekil 5: Klasöre Yeni Bir Sınıf App_Code Ekle (Tam boyutlu görüntüyü görüntülemek için tıklayın)

Ardından, olay için ColumnChanging , UnitPrice, ve UnitsInStockUnitsOnOrder sütun değerlerinin (değilseReorderLevel) sıfırdan büyük veya sıfıra eşit olmasını NULLsağlayan bir olay işleyicisi oluşturun. Bu tür bir sütun aralık dışındaysa, bir 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. Adım: BLL'nin Sınıflarına Özel İş Kuralları Ekleme

Alan düzeyinde doğrulamaya ek olarak, tek sütun düzeyinde ifade edilemeyen farklı varlıkları veya kavramları içeren üst düzey özel iş kuralları olabilir, örneğin:

  • Bir ürün durdurulursa, UnitPrice güncellenemez
  • Bir çalışanın ikamet ettiği ülke, yöneticisinin ikamet ettiği ülke ile aynı olmalıdır
  • Tedarikçi tarafından sağlanan tek ürün olan bir ürünün üretimi durdurulamaz

BLL sınıfları, uygulamanın iş kurallarına uyulduğundan emin olmak için denetimler içermelidir. Bu denetimler doğrudan uygulandıkları yöntemlere eklenebilir.

İş kurallarımızın, belirli bir tedarikçiden gelen tek ürün olması durumunda bir ürünün üretimi durduruldu olarak işaretlenemeyeceğini belirttiğini hayal edin. Diğer bir deyişle, X ürünü Y tedarikçisinden satın aldığımız tek ürün olsaydı, X'i durduruldu olarak işaretleyemezdik; Bununla birlikte, Y tedarikçisi bize A, B ve C olmak üzere üç ürün tedarik ettiyse, bunlardan herhangi birini veya tümünü durduruldu olarak işaretleyebiliriz. Garip bir iş kuralı, ancak iş kuralları ve sağduyu her zaman uyumlu değildir!

Bu iş kuralını yöntemde UpdateProducts uygulamak için, olarak Discontinued ayarlanıp ayarlanmadığını True kontrol ederek başlarız ve eğer öyleyse, bu ürünün tedarikçisinden kaç ürün satın aldığımızı belirlemek için ararızGetProductsBySupplierID. Bu tedarikçiden yalnızca bir ürün satın alınırsa, bir 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

Sunu katmanındaki doğrulama hatalarına yanıt verme

BLL'yi sunu katmanından çağırırken, yükseltilebilecek herhangi bir özel durumu işlemeye çalışıp çalışmayacağımıza veya bunların ASP.NET'a kadar baloncuklanmasına izin verip vermeyeceğimize karar verebiliriz (bu, ' olayını HttpApplicationError yükseltir). BLL ile programlı olarak çalışırken bir istisnayı ele almak için bir Deneyin... Aşağıdaki örnekte gösterildiği gibi catch bloğu:

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

Gelecekteki öğreticilerde göreceğimiz gibi, veri eklemek, güncelleştirmek veya silmek için bir veri Web denetimi kullanılırken BLL'den kabarcık oluşturan özel durumları işlemek, kodu bloklar halinde Try...Catch sarmalamak yerine doğrudan bir olay işleyicisinde işlenebilir.

Özet

İyi tasarlanmış bir uygulama, her biri belirli bir rolü kapsülleyen farklı katmanlar halinde hazırlanır. Bu makale serisinin ilk öğreticisinde, Yazılan Veri Kümelerini kullanarak bir Veri Erişim Katmanı oluşturduk; Bu öğreticide, uygulamamızın klasöründe DAL'ımıza App_Code çağrı yapan bir dizi sınıf olarak bir İş Mantığı Katmanı oluşturduk. BLL, uygulamamız için alan düzeyi ve iş düzeyi mantığını uygular. Bu öğreticide yaptığımız gibi ayrı bir BLL oluşturmanın yanı sıra, başka bir seçenek de TableAdapters'ın yöntemlerini kısmi sınıfların kullanımıyla genişletmektir. Bununla birlikte, bu tekniği kullanmak, mevcut yöntemleri geçersiz kılmamıza izin vermez ve DAL'ımızı ve BLL'mizi bu makalede benimsediğimiz yaklaşım kadar net bir şekilde ayırmaz.

DAL ve BLL tamamlandıktan sonra sunum katmanımıza başlamaya hazırız. Sonraki öğreticide, veri erişimi konularından kısa bir sapma yapacağız ve öğreticiler boyunca kullanmak üzere tutarlı bir sayfa düzeni tanımlayacağız.

Mutlu Programlama!

Yazar Hakkında

Yedi ASP/ASP.NET kitabının yazarı ve 4GuysFromRolla.com kurucusu Scott Mitchell, 1998'den beri Microsoft Web teknolojileriyle çalışmaktadır. Scott bağımsız bir danışman, eğitmen ve yazar olarak çalışır. Son kitabı Sams Teach Yourself ASP.NET 24 Hours 2.0'dır. Ona adresinden mitchell@4GuysFromRolla.comulaşabilirsiniz.

Özel Teşekkürler

Bu eğitim serisi, birçok yararlı kişi tarafından incelendi. Bu öğreticinin baş gözden geçirenleri Liz Shulok, Dennis Patterson, Carlos Santos ve Hilton Giesenow'du. Yaklaşan MSDN makalelerimi gözden geçirmek istiyor musunuz? Öyleyse, mitchell@4GuysFromRolla.com'a bir mesaj bırakın.