在ASP.NET 2.0中操作数据之三十八:处理BLL和DAL的异常_自学过程

导言

  在DataList里编辑和删除数据概述里,我们创建了一个提供简单编辑和删除功能的DataList。虽然功能上已经完整了,但是对用户来说是不友好的。因为所有在编辑和删除过程中产生的异常都是未处理的。比如,遗漏了输入product的name,或者编辑product时在price里输入“Very affordable!”,都会抛出异常。而由于在代码里未捕捉这些异常,页面会显示ASP.NET运行时的详细错误信息。

  如我们在在ASP.NET页面中处理BLL/DAL层的异常里看到的,如果BLL或DAL里发生异常,详细的信息会返回到ObjectDataSource,然后再到GridView。我们已经学习了如何优雅的处理这些异常:为ObjectDataSource或GridView创建Updated或RowUpdated事件处理,检查异常,然后指明异常被处理。

  然而在使用DataList时,我们并没有通过ObjectDataSource来更新和删除数据。我们是直接通过BLL来实现的。为了检测到 BLL或DAL的异常,我们需要在ASP.NET页里写异常处理代码。本章我们将学习在使用DataList编辑时如何巧妙的处理异常。

  注意:在DataList里编辑和删除数据概述里,我们讨论了几种不同的编辑和删除数据的方法,其中一些会涉及到使用ObjectDataSource来编辑和删除。如果你用这些技术的话,你可以直接通过ObjectDataSource的Updated或Deleted 事件处理中处理这些异常。

第一步: 创建一个可编辑的DataList

  首先创建一个可编辑的DataList。打开EditDeleteDataList文件夹下的ErrorHandling.aspx页,添加一个ID为Products的DataList和一个名为ProductsDataSource的ObjectDataSouce。在SELECT标签下选择ProductsBLL类的GetProducts()方法。在INSERT,UPDATE和DELETE标签里选择None.


图 1: 配置ObjectDataSource

  完成ObjectDataSouce后,Visual Studio会自动创建一个ItemTemplate。用显示每个product的name和price并包含一个Edit button的ItemTemplate代替它,然后创建一个用TextBox显示name和price,并包含一个Update button和Cancel button的EditItemTemplate。最后将DataList的RepeatColumns属性设为2。

  做完这些后,你的声明代码应该和下面的差不多。检查并确保Edit,Cancel和Update button的CommandName属性,分别被设为“Edit”, “Cancel”, 和“Update”。

<asp:DataList ID="Products" runat="server" DataKeyField="ProductID"
 DataSourceID="ProductsDataSource" RepeatColumns="2">
 <ItemTemplate>
  <h5>
   <asp:Label runat="server" ID="ProductNameLabel"
    Text='<%# Eval("ProductName") %>' />
  </h5>
  Price:
   <asp:Label runat="server" ID="Label1"
    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
  <br />
   <asp:Button runat="server" id="EditProduct" CommandName="Edit"
    Text="Edit" />
  <br />
  <br />
 </ItemTemplate>
 <EditItemTemplate>
  Product name:
   <asp:TextBox ID="ProductName" runat="server"
    Text='<%# Eval("ProductName") %>' />
  <br />
  Price:
   <asp:TextBox ID="UnitPrice" runat="server"
    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
  <br />
  <br />
   <asp:Button ID="UpdateProduct" runat="server" CommandName="Update"
    Text="Update" />
   <asp:Button ID="CancelUpdate" runat="server" CommandName="Cancel"
    Text="Cancel" />
 </EditItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
 SelectMethod="GetProducts" TypeName="ProductsBLL"
 OldValuesParameterFormatString="original_{0}">
</asp:ObjectDataSource> 

         

  注意:本章里DataList的view state必须开启。浏览一下页面,见图2。


图 2: 每个Product 都包含一个Edit Button

  现在Edit button只是引起一个postback —还不能将product变成可编辑的。为了实现编辑功能,我们需要为EditCommand,CancelCommand和UpdateCommand创建事件处理。EditCommand和CancelCommand事件仅仅只需要更新DataList的EditItemIndex属性,并重新绑定数据到DataList。

protected void Products_EditCommand(object source, DataListCommandEventArgs e)
{
 // Set the DataList's EditItemIndex property to the
 // index of the DataListItem that was clicked
 Products.EditItemIndex = e.Item.ItemIndex;
 // Rebind the data to the DataList
 Products.DataBind();
}
protected void Products_CancelCommand(object source, DataListCommandEventArgs e)
{
 // Set the DataList's EditItemIndex property to -1
 Products.EditItemIndex = -1;
 // Rebind the data to the DataList
 Products.DataBind();
}

       

  UpdateCommand事件处理稍微麻烦一点。它需要从DataKey集合里读取被编辑的product的ProductID,和EditItemTemplate里的TextBox里的product的name和price,然后调用ProductsBLL类的UpdateProduct方法,最后返回到DataList编辑前的状态。

  我们在这里使用 在DataList里编辑和删除数据概述 里的UpdateCommand事件处理代码。

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
 // Read in the ProductID from the DataKeys collection
 int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
 // Read in the product name and price values
 TextBox productName = (TextBox)e.Item.FindControl("ProductName");
 TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");
 string productNameValue = null;
 if (productName.Text.Trim().Length > 0)
  productNameValue = productName.Text.Trim();
 decimal? unitPriceValue = null;
 if (unitPrice.Text.Trim().Length > 0)
  unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(),
   System.Globalization.NumberStyles.Currency);
 // Call the ProductsBLL's UpdateProduct method...
 ProductsBLL productsAPI = new ProductsBLL();
 productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);
 // Revert the DataList back to its pre-editing state
 Products.EditItemIndex = -1;
 Products.DataBind();
}

  在有非法输入的时候— 可能是不正确的price格式,比如“-$5.00”,或者忽略了product的name— 就会引起异常。由于UpdateCommand事件处理还没有处理异常,页面会出现ASP.NET运行时错误。见图3。


图 3: 未处理异常发生时,用户会看到这样的错误页面

第二步: 在UpdateCommand Event Handler里处理异常

  更新流程中,异常可能发生在UpdateCommand事件处理,或BLL或DAL里。比如,如果用户输入了一个“太贵”的价格,UpdateCommand 事件处理里的Decimal.Parse 会抛出FormatException 异常。如果用户忽略了product的name或者price是一个负数,DAL会抛出异常。

当异常发生时,我们希望显示自己定义的信息。添加一个ID为ExceptionDetails的Label控件到页面上,通过设置CssClass属性为Warning CSS类来将Text设置为红色,特大,加粗的意大利字体。这个类在Styles.css文件里定义。

  异常发生时,我们只希望这个 Label显示一次。也就是说,在后面postback的时候,Label的警告信息需要隐藏起来。这个可以通过清除Label的Text属性或者将Visible属性设为False(在Page_Load里)(如我们在在ASP.NET页面中处理BLL/DAL层的异常 里做的那样)或者禁用Label的view state来实现。我们这里用后一种方法。

<asp:Label ID="ExceptionDetails" EnableViewState="False" CssClass="Warning"
 runat="server" />

  异常发生时,我们将异常的信息显示在Label的Text属性上。由于view state被禁用了,后面再postback的话,Text属性会自动的丢失,回到缺省值(空字符串),这样就隐藏了警告信息。

  异常发生时将信息显示在页面上,我们需要在UpdateCommand事件处理里添加Try....Catch块。Try的那部分包含可能抛出异常的代码,Catch部分包含当出现异常时需要执行的代码。更多的Try..Catch块信息参考Exception Handling Fundamentals 。

protected void Products_UpdateCommand(object source, DataListCommandEventArgs e)
{
 // Handle any exceptions raised during the editing process
 try
 {
  // Read in the ProductID from the DataKeys collection
  int productID = Convert.ToInt32(Products.DataKeys[e.Item.ItemIndex]);
  ... Some code omitted for brevity ...
 }
 catch (Exception ex)
 {
  // TODO: Display information about the exception in ExceptionDetails
 }
}

           

  无论Try块里抛出何种类型的异常,Catch块的代码都会执行。抛出异常的类型—DbException, NoNullAllowedException, ArgumentException等 — 取决于第一个错误。如果是数据库级别的问题,会抛出DbException 。如果是UnitPrice, UnitsInStock, UnitsOnOrder, 或ReorderLevel 字段有非法值,会抛出ArgumentException (我们在ProductsDataTable里已经添加过验证字段值的代码,见创建一个业务逻辑层 )

  我们可以根据捕捉到的异常的类型来为用户提供更好的帮助。下面的代码— 和在ASP.NET页面中处理BLL/DAL层的异常 中基本上一样— 提供了这个功能:

private void DisplayExceptionDetails(Exception ex)
{
 // Display a user-friendly message
 ExceptionDetails.Text = "There was a problem updating the product. ";
 if (ex is System.Data.Common.DbException)
  ExceptionDetails.Text += "Our database is currently experiencing problems.
   Please try again later.";
 else if (ex is NoNullAllowedException)
  ExceptionDetails.Text += "There are one or more required fields that are
   missing.";
 else if (ex is ArgumentException)
 {
  string paramName = ((ArgumentException)ex).ParamName;
  ExceptionDetails.Text +=
   string.Concat("The ", paramName, " value is illegal.");
 }
 else if (ex is ApplicationException)
  ExceptionDetails.Text += ex.Message;
}

       

  最后仅仅只需要调用DisplayExceptionDetails方法。

  完成Try..Catch后,用户会看到更有用的错误信息,如图4,5所示。注意在异常出现时,DataList仍然保持在可编辑的模式下。这是因为异常发生时,控制流程马上转到Catch块里,忽略了将DataList转到编辑前状态的代码。


图 4: 用户忽略了必填字段时的错误信息


图 5: 输入非法价格时的错误信息

总结

  GridView和ObjectDataSource提供了在更新和删除过程中包含异常信息的事件处理和指明异常是否被处理的属性。而直接使用BLL的DataList没有这些特性,我们需要亲自处理这些异常。

本章我们学习了如何在DataList的更新过程中在UpdateCommand里添加Try...Catch块来处理异常。如果有任何异常发生,Catch块里的代码会执行,将错误信息显示在ExceptionDetails Label上。

  现在,DataList并没有在第一时间阻止异常的发生。尽管我们知道一个负的price值会产生异常,我们也没有添加阻止用户输入这样的值的功能。在后面的几章里,我们将学习如何通过在EditItemTemplate里添加验证控件来验证用户的输入从而减少这些异常的发生。

  祝编程愉快!

作者简介

  本系列教程作者 Scott Mitchell,著有六本ASP/ASP.NET方面的书,是4GuysFromRolla.com的创始人,自1998年以来一直应用 微软Web技术。大家可以点击查看全部教程《[翻译]Scott Mitchell 的ASP.NET 2.0数据教程》,希望对大家的学习ASP.NET有所帮助。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索asp.net
, 异常
, datalist
, dal
, BLL
Try...Catch
,以便于您获取更多的相关知识。

时间: 2024-09-17 04:55:58

在ASP.NET 2.0中操作数据之三十八:处理BLL和DAL的异常_自学过程的相关文章

在ASP.NET 2.0中操作数据之三十:格式化DataList和Repeater的数据_自学过程

导言 在前面的教程里我们学习了DataList提供了一些风格样式的属性.而且我们还学习了如何定义HeadStyle, ItemStyle, AlternatingItemStyle, 和SelectedItemStyle等属性的默认CSS.除了这四个属性外,DataList还提供了其它属性,比如Font, ForeColor, BackColor, 和BorderWidth.而Repeater没有提供任何这样的属性.如果你需要用Reperter来实现这些效果,你就需要在templates里直接写

在ASP.NET 2.0中操作数据之三十二:数据控件的嵌套_自学过程

导言 除了静态HTML和数据绑定语法,template也可以包含Web控件和用户控件.这些控件的属性可以通过声明语法,数据绑定语法或在服务器端通过事件处理编程来设置. 通过将控件嵌入到template里,可以自定义界面,提升用户体验.例如,在在GridView控件中使用TemplateField 里,我们学习了如何通过在GridView的TemplateField里加一个Calendar控件来表示员工的雇佣日期.在给编辑和新增界面增加验证控件 和定制数据修改界面 里,我们学习了如何通过添加验证控

ASP.NET 2.0数据教程之三十八:处理BLL和DAL的异常

返回"ASP.NET 2.0数据教程目录" 在 综叙:在DataList里编辑和删除数据 里,我们创建了一个提供简单编辑和 删除功能的DataList.虽然功能上已经完整了,但是对用户来说是不友好的.因 为所有在编辑和删除过程中产生的异常都是未处理的.比如,遗漏了输入product 的name,或者编辑product时在price里输入"Very affordable!", 都会抛出异常.而由于在代码里未捕捉这些异常,页面会显示ASP.NET运行时的详 细错误信息.

在ASP.NET 2.0中操作数据之七十:配置数据库连接和命令等级设置_自学过程

导言: 在本系列我们用类型化的DataSets来构建数据访问层.就像在第一章探讨的那样,类型化DataSets的DataTables用作存储数据的"仓库",而TableAdapters作为连接数据库的通道,以检索.修改数据.TableAdapters 将处理数据库的很多复杂的细节进行了封装,将我们解脱出来,免去了写代码连接数据库.发出命名.向DataTable填充数据的痛苦. 不过在某些时候我们需要深入的探究TableAdapter,直接写代码处理ADO.NET对象.在第61章<

在ASP.NET 2.0中操作数据之五十二:使用FileUpload上传文件_自学过程

导言: 到目前为止,我们的教程围绕的是text数据.然而,很多应用程序既需要处理text数据,也需要处理二进制数据.比如招聘网站可能需要用户上传Word或PDF格式的简历. 使用二进制数据面临一项挑战:在应用程序中如何存储二进制数据.我们必须更新添加记录的界面以支持用户上传本地电脑中的文件,并添加额外的功能以下载某条记录的相关二进制数据.本章以及接下来的3章,我们探讨如何处理这些问题.在本系列教程结束时,我们将创建一个功能完善的应用程序,它为每种类型的记录提供相关的图片和PDF小册子. 在本系列

在ASP.NET 2.0中操作数据之四十九:为GridView控件添加RadioButton_自学过程

导言: GridView控件提供了大量的内置功能.它包含了一系列的域(field)来显示诸如text.images.hyperlinks和buttons.另外它支持模板(template)用于用户自定义界面.我们可以构建这样一个GridView控件,用户仅需要点击控件里的一个按钮,每一条记录行都可以选择.编辑.删除.除了控件本身内置的功能外,在某些情况下,我们添加一些额外的.控件没有内置的功能.在本章及接下来的2篇教程里我们将探讨如何优化GridView,以支持额外的功能. 本篇及接下来的教程将

在ASP.NET 2.0中操作数据之五十九:使用SQL缓存依赖项SqlCacheDependency_自学过程

导言: 在56和57章探讨的缓存技术使用的是基于时间的缓存周期,当过了某段时间后便将缓存数据从内存清除.当设置缓存时间为x秒时,数据在x秒内都是"新"的.当然,就像在60章谈到的那样,对静态数据来说,x可延伸到web应用程序的整个生命周期(lifetime). 当缓存数据时,基于时间周期的技术因为其易用性而常常被采用,不过又常常不那么完美.理想的状态是这样的:数据库数据还是应缓存在内存,直到源数据(underlying data)发生改变时才从内存清除.这样的话可以最大化的获取缓存带来

在ASP.NET 2.0中操作数据之三十九:在DataList的编辑界面里添加验证控件_自学过程

导言 到目前为止的讨论编辑DataList的教程里,没有包含任何验证用户的输入,即使是用户非法输入- 遗漏了product的name或者负的price- 会导致异常.在前面一章里我们学习了如何在DataList的UpdateCommand事件处理中添加异常处理代码,以便在出现异常时捕捉它并显示友好的错误信息.然而理想的编辑界面应该包含验证控件,用来在第一时间里阻止用户输入一些非法数据. 本章我们将学习在DataList的EditItemTemplate里添加验证控件从而提供一个更安全的编辑界面,

在ASP.NET 2.0中操作数据之三十六:在DataList里编辑和删除数据概述_自学过程

导言 概述插入.更新和删除数据 里我们已经学习了如何使用GridView等控件来插入,更新删除数据.通过ObjectDataSource和其它数据控件仅仅只需要在智能标签里勾一下checkbox就完成了,不需要写任何代码.而DataList没有这些内置的功能.我们可以使用1.x 里的方法来实现这些功能.在本章我们将看到,DataList提供了一些事件和属性来完成我们的目的,为此我们需要写一些代码. 本章我们首先学习如何创建一个支持编辑和删除数据的DataList.后面的教程里我们将学习一些高级的