通过设置属性为,事件处理程序指示该异常已经被处理。因此,这个异常不会传送到ASP.NET运行时。
注意: 图9和图10显示了一种得体的方式处理不正确的用户输入所引发的异常。可是,更理想地,这些不正确的输入不应该到达业务逻辑层,因为ASP.NET页面应该在调用ProductsBLL类的UpdateProduct方法之前就确保用户的输入是有效的。我们在下一节里将会看看如何添加validation控件到编辑和插入界面从而保证提交到业务逻辑层的数据遵循业务规则。validation控件不但可以阻止调用UpdateProduct方法直到用户提供有效的数据,还可以为定位数据输入问题提供一个更充满提示性的用户体验。
第三步: 适当地处理BLL层异常
当插入、更新或删除数据时,面对一个数据相关的错误时数据访问层会抛出一个异常。数据库可能未连线,一个必需的数据库表字段可能未指定值,或者违反了某个表间约束。除了确定的数据相关的异常外,业务逻辑层也使用异常指示违反了业务逻辑。在创建一个业务逻辑层 这一节里,作为例子,我们添加了一个业务规则检查最初的UpdateProduct重载。特别地,如果用户标记一个产品为停止供应,我们要求这个产品不能是该供应商唯一供应的产品。如果违反了这个条件,抛出一个ApplicationException异常。
在这一节里,我们给UpdateProduct重载增加一个业务规则:禁止把UnitPrice字段的值设置为超过原来的两倍。为了实现这一点,调整UpdateProduct重载以使它可以执行这个检查并且在违反该规则时抛出一个ApplicationException异常。此更新方法如下:
public bool UpdateProduct(string productName, decimal? unitPrice, short? unitsInStock, 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]; // Make sure the price has not more than doubled if (unitPrice != null && !product.IsUnitPriceNull()) if (unitPrice > product.UnitPrice * 2) throw new ApplicationException( "When updating a product price," + " the new price cannot exceed twice the original price."); product.ProductName = productName; if (unitPrice == null) product.SetUnitPriceNull(); else product.UnitPrice = unitPrice.Value; if (unitsInStock == null) product.SetUnitsInStockNull(); else product.UnitsInStock = unitsInStock.Value; // Update the product record int rowsAffected = Adapter.Update(product); // Return true if precisely one row was updated, otherwise false return rowsAffected == 1; }
通过这个修改,任何超过现有价格两倍的价格更新都回引发一个ApplicationException异常被抛出。就像DAL中引发的异常一样,这个BLL引发的ApplicationException异常可以在GridView的RowUpdated事件处理程序中被侦测并处理。实际上,我们已有的RowUpdated事件处理程序的代码可以正确地发现到这个异常并显示ApplicationException的Message属性的值。图11显示的是当一个用户试图将产品“Chai”的价格更新为$50.00时的截屏,这超过了它原有价格$19.95的两倍。
图 11: 这个业务规则不接受价格增长超出产品现有价格的两倍
注意: 理想化地我们的业务规则不应该在UpdateProduct方法重载里而应该在一个公共的方法中。这留作读者练习。
总结
在插入、更新或删除操作的过程中,数据Web控件和ObjectDataSource控件都包含了pre- 和post-级的事件,它们记录着当前的操作。正如我们在本节和前面的一节里所看到的,当使用一个可编辑的GridView时,GridView的RowUpdating事件在ObjectDataSource的Updating事件之后触发,此时update命令发送到ObjectDataSource的隐含对象。完成了此操作,在GridView的RowUpdated事件之后,触发ObjectDataSource的Updated事件。