我们现有的ProductsBLL类包含批量更新和直接发送数据库的模式的例子。AddProduct方法和 UpdateProduct重载都使用了批量更新模式,通过一个ProductRow实例发送到TableAdapter的Update方法。另一方面,DeleteProduct方法则使用直接发送到数据库的模式,调用TableAdapter的Delete(productID)方法。在新的ProductsOptimisticConcurrency TableAdapter里,发送到数据库的方法现还要求传入原始的值。例如,Delete方法
现在要求十个输入参数:原始的ProductID、ProductName、SupplierID、CategoryID、QuantityPerUnit、UnitPrice、UnitsInStock、UnitsOnOrder、ReorderLevel和Discontinued。它在发送到数据库的DELETE语句的WHERE子句里使用这些额外的输入参数,仅仅删除当前数据库的值与原始值一致的指定记录。
使用批量更新模式时,如果标记给TableAdapter的Update使用的方法没有更改,那么代码就需要同时记录原始值和新的值。然而,与其在我们现有的ProductsBLL类的基础上试图使用启用了开放式并发的DAL,不如让我们重新创意一个业务逻辑类支持我们新的DAL。在App_Code文件夹下的BLL子文件夹里,添加一个名为ProductsOptimisticConcurrencyBLL的新类。
图 12: 添加ProductsOptimisticConcurrencyBLL类到BLL文件夹
然后,在ProductsOptimisticConcurrencyBLL类里添加如下代码:
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 NorthwindOptimisticConcurrencyTableAdapters; [System.ComponentModel.DataObject] public class ProductsOptimisticConcurrencyBLL { private ProductsOptimisticConcurrencyTableAdapter _productsAdapter = null; protected ProductsOptimisticConcurrencyTableAdapter Adapter { get { if (_productsAdapter == null) _productsAdapter = new ProductsOptimisticConcurrencyTableAdapter(); return _productsAdapter; } } [System.ComponentModel.DataObjectMethodAttribute (System.ComponentModel.DataObjectMethodType.Select, true)] public NorthwindOptimisticConcurrency.ProductsOptimisticConcurrencyDataTable GetProducts() { return Adapter.GetProducts(); } }
注意在类的声明开始之前的using NorthwindOptimisticConcurrencyTableAdapters语句。命名空间NorthwindOptimisticConcurrencyTableAdapters包含了类ProductsOptimisticConcurrencyTableAdapter,它提供DAL的方法。并且,在类声明之前我们还能找到System.ComponentModel.DataObject属性标志,它指示Visual Studio把该类包含在ObjectDataSource向导的数据对象下拉列表中。
类ProductsOptimisticConcurrencyBLL的Adapter属性提供快速访问ProductsOptimisticConcurrencyTableAdapter类的一个实例,并和我们最初的BLL类(ProductsBLL、CategoriesBLL等等)相似。最后,方法GetProducts()仅仅是调用DAL的GetProdcuts()方法并返回一个ProductsOptimisticConcurrencyDataTable对象,该对象由对应数据库里每一个产品记录的ProductsOptimisticConcurrencyRow实例组成。
使用支持开放式并发的发送到数据库的模式删除一个产品记录
当使用支持开放式并发的DAL发送到数据库的模式,方法必须传入新值和原始值。对删除来说,这没有新的值,所以仅仅需要传入原始值。那么,在我们的BLL里,我们必须接收所有原始值所为输入参数。让ProductsOptimisticConcurrencyBLL类的DeleteProduct方法使用这个发送到数据的方法。这意味着此方法必须接受所有的十个产品数据字段作为输入参数,并传送这些参数到DAL,如下面的代码所示:
[System.ComponentModel.DataObjectMethodAttribute (System.ComponentModel.DataObjectMethodType.Delete, true)] public bool DeleteProduct (int original_productID, string original_productName, int? original_supplierID, int? original_categoryID, string original_quantityPerUnit, decimal? original_unitPrice, short? original_unitsInStock, short? original_unitsOnOrder, short? original_reorderLevel, bool original_discontinued) { int rowsAffected = Adapter.Delete(original_productID, original_productName, original_supplierID, original_categoryID, original_quantityPerUnit, original_unitPrice, original_unitsInStock, original_unitsOnOrder, original_reorderLevel, original_discontinued); // Return true if precisely one row was deleted, otherwise false return rowsAffected == 1; }
如果这些在GridView(或者是DetailsView、FormView)最后一次加载时的原始值跟用户点击删除按钮时数据库中的值不一致, WHERE子句将不能匹配任何数据库记录,这就没有记录会受到影响。因此,TableAdapter的Delete方法将返回0并且BLL的DeleteProduct方法返回false。
使用支持开放式并发的批量更新模式修改一个产品记录