ASP.NET 페이지에서 BLL 및 DAL 수준의 예외 처리(VB)Handling BLL- and DAL-Level Exceptions in an ASP.NET Page (VB)

Scott Mitchellby Scott Mitchell

샘플 앱 다운로드 또는 PDF 다운로드Download Sample App or Download PDF

이 자습서에서는 ASP.NET data 웹 컨트롤의 삽입, 업데이트 또는 삭제 작업을 수행 하는 동안 예외가 발생 하는 정보를 제공 하는 오류 메시지를 표시 하는 방법을 알아봅니다.In this tutorial we will see how to display a friendly, informative error message should an exception occur during an insert, update, or delete operation of an ASP.NET data Web control.

소개Introduction

계층화 된 응용 프로그램 아키텍처를 사용 하는 ASP.NET 웹 응용 프로그램의 데이터 작업에는 다음과 같은 세 가지 일반적인 단계가 포함 됩니다.Working with data from an ASP.NET web application using a tiered application architecture involves the following three general steps:

  1. 호출 해야 하는 비즈니스 논리 계층의 메서드와 전달할 매개 변수 값을 결정 합니다.Determine what method of the Business Logic Layer needs to be invoked and what parameter values to pass it. 매개 변수 값은 하드 코딩 되거나, 프로그래밍 방식으로 할당 되거나, 사용자가 입력 한 입력이 될 수 있습니다.The parameter values can be hard coded, programmatically-assigned, or inputs entered by the user.
  2. 메서드를 호출합니다.Invoke the method.
  3. 결과를 처리 합니다.Process the results. 데이터를 반환 하는 BLL 메서드를 호출 하는 경우 데이터를 데이터 웹 컨트롤에 바인딩하는 작업이 포함 될 수 있습니다.When calling a BLL method that returns data, this may involve binding the data to a data Web control. 데이터를 수정 하는 BLL 메서드의 경우 반환 값을 기반으로 하는 일부 작업을 수행 하거나 2 단계에서 발생 한 예외를 정상적으로 처리 하는 작업을 포함할 수 있습니다.For BLL methods that modify data, this may include performing some action based on a return value or gracefully handling any exception that arose in Step 2.

이전 자습서에서 살펴본 것 처럼 ObjectDataSource와 데이터 웹 컨트롤 모두 1 및 3 단계에 대 한 확장성을 제공 합니다.As we saw in the previous tutorial, both the ObjectDataSource and the data Web controls provide extensibility points for Steps 1 and 3. 예를 들어 GridView는 해당 ObjectDataSource의 UpdateParameters 컬렉션에 필드 값을 할당 하기 전에 RowUpdating 이벤트를 발생 시킵니다. ObjectDataSource가 작업을 완료 한 후 RowUpdated 이벤트가 발생 합니다.The GridView, for example, fires its RowUpdating event prior to assigning its field values to its ObjectDataSource's UpdateParameters collection; its RowUpdated event is raised after the ObjectDataSource has completed the operation.

1 단계에서 발생 하는 이벤트를 이미 검사 했으며이 이벤트를 사용 하 여 입력 매개 변수를 사용자 지정 하거나 작업을 취소할 수 있는 방법을 살펴보았습니다.We've already examined the events that fire during Step 1 and have seen how they can be used to customize the input parameters or cancel the operation. 이 자습서에서는 작업이 완료 된 후에 발생 하는 이벤트에 주목 합니다.In this tutorial we'll turn our attention to the events that fire after the operation has completed. 이러한 사후 수준 이벤트 처리기를 사용 하면 작업 중에 예외가 발생 했는지 여부를 확인 하 고 정상적으로 처리할 수 있습니다. 표준 ASP.NET를 기본적으로 사용 하는 대신 화면에 친숙 한 정보 오류 메시지를 표시 합니다. 예외 페이지.With these post-level event handlers we can, among other things, determine if an exception occurred during the operation and handle it gracefully, displaying a friendly, informative error message on the screen rather than defaulting to the standard ASP.NET exception page.

이러한 사후 수준 이벤트 작업을 설명 하기 위해 편집 가능한 GridView의 제품을 나열 하는 페이지를 만들어 보겠습니다.To illustrate working with these post-level events, let's create a page that lists the products in an editable GridView. 제품을 업데이트 하는 경우 예외가 발생 하는 경우 ASP.NET 페이지가 GridView 위에 오류가 발생 했음을 설명 하는 짧은 메시지를 표시 합니다.When updating a product, if an exception is raised our ASP.NET page will display a short message above the GridView explaining that a problem has occurred. 이제 시작하겠습니다.Let's get started!

1 단계: 편집 가능한 제품 GridView 만들기Step 1: Creating an Editable GridView of Products

이전 자습서에서는 두 개의 필드인 ProductNameUnitPrice를 사용 하 여 편집 가능한 GridView를 만들었습니다.In the previous tutorial we created an editable GridView with just two fields, ProductName and UnitPrice. 이렇게 하려면 각 product 필드에 대 한 매개 변수 대신 세 개의 입력 매개 변수 (제품 이름, 단가 및 ID)만 허용 하는 ProductsBLL 클래스의 UpdateProduct 메서드에 대 한 추가 오버 로드를 만들어야 합니다.This required creating an additional overload for the ProductsBLL class's UpdateProduct method, one that only accepted three input parameters (the product's name, unit price, and ID) as opposed a parameter for each product field. 이 자습서에서는이 기법을 다시 연습 하 여 제품의 이름, 단위 당 수량, 단가 및 재고 단위를 표시 하는 편집 가능한 GridView를 만들고 재고의 이름, 단가 및 단위도 편집할 수 있습니다.For this tutorial, let's practice this technique again, creating an editable GridView that displays the product's name, quantity per unit, unit price, and units in stock, but only allows the name, unit price, and units in stock to be edited.

이 시나리오를 수용 하려면 제품의 이름, 단가, 재고 단위 및 ID의 네 가지 매개 변수를 허용 하는 UpdateProduct 메서드의 다른 오버 로드가 필요 합니다.To accommodate this scenario we'll need another overload of the UpdateProduct method, one that accepts four parameters: the product's name, unit price, units in stock, and ID. ProductsBLL 클래스에 다음 메서드를 추가합니다.Add the following method to the ProductsBLL class:

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, True)> _
Public Function UpdateProduct _
    (ByVal productName As String, ByVal unitPrice As Nullable(Of Decimal), _
ByVal unitsInStock As Nullable(Of Short), ByVal 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 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
    Dim rowsAffected As Integer = Adapter.Update(product)
    Return rowsAffected = 1
End Function

이 메서드가 완료 되 면 이러한 4 가지 특정 제품 필드를 편집할 수 있는 ASP.NET 페이지를 만들 준비가 되었습니다.With this method complete, we're ready to create the ASP.NET page that allows for editing these four particular product fields. EditInsertDelete 폴더에서 ErrorHandling.aspx 페이지를 열고 디자이너를 통해 페이지에 GridView를 추가 합니다.Open the ErrorHandling.aspx page in the EditInsertDelete folder and add a GridView to the page through the Designer. GridView를 새 ObjectDataSource에 바인딩하여 Select() 메서드를 ProductsBLL 클래스의 GetProducts() 메서드에 매핑하고 Update() 메서드를 앞서 만든 UpdateProduct 오버 로드에 매핑합니다.Bind the GridView to a new ObjectDataSource, mapping the Select() method to the ProductsBLL class's GetProducts() method and the Update() method to the UpdateProduct overload just created.

4 개의 입력 매개 변수를 허용 하는 UpdateProduct 메서드 오버 로드를 사용 Use the UpdateProduct Method Overload That Accepts Four Input Parameters

그림 1: 4 개의 입력 매개 변수를 허용 하는 UpdateProduct 메서드 오버 로드 사용 (전체 크기 이미지를 보려면 클릭)Figure 1: Use the UpdateProduct Method Overload That Accepts Four Input Parameters (Click to view full-size image)

그러면 4 개의 매개 변수가 있는 UpdateParameters 컬렉션과 각 product 필드에 대 한 필드가 있는 GridView가 만들어집니다.This will create an ObjectDataSource with an UpdateParameters collection with four parameters and a GridView with a field for each of the product fields. ObjectDataSource의 선언적 태그는 OldValuesParameterFormatString 속성에 original_{0}값을 할당 합니다. 그러면 BLL 클래스의 original_productID 전달 된 입력 매개 변수가 필요 하지 않기 때문에 예외가 발생 합니다.The ObjectDataSource's declarative markup assigns the OldValuesParameterFormatString property the value original_{0}, which will cause an exception since our BLL class's don't expect an input parameter named original_productID to be passed in. 선언적 구문에서이 설정을 완전히 제거 해야 합니다. 그렇지 않으면 {0}기본값으로 설정 합니다.Don't forget to remove this setting altogether from the declarative syntax (or set it to the default value, {0}).

그런 다음 ProductName, QuantityPerUnit, UnitPriceUnitsInStock BoundFields만 포함 하도록 GridView를 줄이려면 상당한 합니다.Next, pare down the GridView to include only the ProductName, QuantityPerUnit, UnitPrice, and UnitsInStock BoundFields. 또한 필요에 따라 필요한 필드 수준 서식 지정 (예: HeaderText 속성 변경)을 자유롭게 적용할 수 있습니다.Also feel free to apply any field-level formatting you deem necessary (such as changing the HeaderText properties).

이전 자습서에서는 읽기 전용 모드 및 편집 모드의 통화로 UnitPrice BoundField의 형식을 지정 하는 방법을 살펴보았습니다.In the previous tutorial we looked at how to format the UnitPrice BoundField as a currency both in read-only mode and edit mode. 여기에서 동일한 작업을 수행해 보겠습니다.Let's do the same here. 그림 2에 표시 된 것 처럼 BoundField의 DataFormatString 속성을 {0:c}로 설정 하 고, 해당 HtmlEncode 속성을 false로 설정 하 고, 해당 ApplyFormatInEditModetrue으로 설정 해야 합니다.Recall that this required setting the BoundField's DataFormatString property to {0:c}, its HtmlEncode property to false, and its ApplyFormatInEditMode to true, as shown in Figure 2.

화폐로 표시 되도록 UnitPrice BoundField 구성 Configure the UnitPrice BoundField to Display as a Currency

그림 2: UnitPrice BoundField를 통화로 표시 하도록 구성 (전체 크기 이미지를 보려면 클릭)Figure 2: Configure the UnitPrice BoundField to Display as a Currency (Click to view full-size image)

편집 인터페이스의 통화로 UnitPrice 서식을 지정 하려면 통화 형식 문자열을 decimal 값으로 구문 분석 하는 GridView의 RowUpdating 이벤트에 대 한 이벤트 처리기를 만들어야 합니다.Formatting the UnitPrice as a currency in the editing interface requires creating an event handler for the GridView's RowUpdating event that parses the currency-formatted string into a decimal value. 마지막 자습서의 RowUpdating 이벤트 처리기도 사용자가 UnitPrice 값을 제공 했는지 확인 합니다.Recall that the RowUpdating event handler from the last tutorial also checked to ensure that the user provided a UnitPrice value. 그러나이 자습서에서는 사용자가 가격을 생략할 수 있습니다.However, for this tutorial let's allow the user to omit the price.

Protected Sub GridView1_RowUpdating(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewUpdateEventArgs) _
    Handles GridView1.RowUpdating
    If e.NewValues("UnitPrice") IsNot Nothing Then
        e.NewValues("UnitPrice") = _
            Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
            System.Globalization.NumberStyles.Currency)
    End If

GridView는 QuantityPerUnit BoundField를 포함 하지만이 BoundField은 표시 목적 으로만 사용 해야 하며 사용자가 편집할 수 없습니다.Our GridView includes a QuantityPerUnit BoundField, but this BoundField should be only for display purposes and should not be editable by the user. 이를 정렬 하려면 BoundFields ' ReadOnly 속성을 true로 설정 하기만 하면 됩니다.To arrange this, simply set the BoundFields' ReadOnly property to true.

QuantityPerUnit BoundField를 읽기 전용으로 설정 Make the QuantityPerUnit BoundField Read-Only

그림 3: QuantityPerUnit BoundField 읽기 전용으로 설정 (전체 크기 이미지를 보려면 클릭)Figure 3: Make the QuantityPerUnit BoundField Read-Only (Click to view full-size image)

마지막으로 GridView의 스마트 태그에서 편집 사용 확인란을 선택 합니다.Finally, check the Enable Editing checkbox from the GridView's smart tag. 이러한 단계를 완료 한 후 ErrorHandling.aspx 페이지의 디자이너는 그림 4와 같이 표시 됩니다.After completing these steps the ErrorHandling.aspx page's Designer should look similar to Figure 4.

필요한 BoundFields를 제외한 모든를 제거 하 고 편집 사용 확인란을 선택 합니다. Remove All But the Needed BoundFields and Check the Enable Editing Checkbox

그림 4: 필요한 BoundFields를 제외 하 고 모두 제거 하 고 편집 사용 확인란을 선택 합니다 (전체 크기 이미지를 보려면 클릭).Figure 4: Remove All But the Needed BoundFields and Check the Enable Editing Checkbox (Click to view full-size image)

이 시점에서 모든 제품의 ProductName, QuantityPerUnit, UnitPriceUnitsInStock 필드가 나열 됩니다. 그러나 ProductName, UnitPriceUnitsInStock 필드만 편집할 수 있습니다.At this point we have a list of all of the products' ProductName, QuantityPerUnit, UnitPrice, and UnitsInStock fields; however, only the ProductName, UnitPrice, and UnitsInStock fields can be edited.

이제 사용자 재고 필드에서 제품의 이름, 가격 및 단위를 쉽게 편집할 수 있습니다.Users Can Now Easily Edit Products' Names, Prices, and Units In Stock Fields

그림 5: 이제 사용자는 재고 필드에서 제품의 이름, 가격 및 단위를 쉽게 편집할 수 있습니다 (전체 크기 이미지를 보려면 클릭).Figure 5: Users Can Now Easily Edit Products' Names, Prices, and Units In Stock Fields (Click to view full-size image)

2 단계: DAL 수준 예외를 정상적으로 처리Step 2: Gracefully Handling DAL-Level Exceptions

편집 가능한 GridView는 사용자가 편집 된 제품의 이름, 가격 및 재고 단위에 대 한 올바른 값을 입력 하는 경우 wonderfully 작동 하지만 잘못 된 값을 입력 하면 예외가 발생 합니다.While our editable GridView works wonderfully when users enter legal values for the edited product's name, price, and units in stock, entering illegal values results in an exception. 예를 들어 ProductName 값을 생략 하면 ProductsRow 클래스의 ProductName 속성에 AllowDBNull 속성이 false로 설정 되어 있기 때문에 system.data.nonullallowedexception 이 throw 됩니다. 데이터베이스가 다운 되 면 데이터베이스에 연결을 시도할 때 TableAdapter에서 SqlException이 throw 됩니다.For example, omitting the ProductName value causes a NoNullAllowedException to be thrown since the ProductName property in the ProductsRow class has its AllowDBNull property set to false; if the database is down, a SqlException will be thrown by the TableAdapter when attempting to connect to the database. 작업을 수행 하지 않고 이러한 예외는 데이터 액세스 계층에서 비즈니스 논리 계층으로 버블링 된 다음 ASP.NET 페이지와 마지막으로 ASP.NET 런타임으로 버블링 됩니다.Without taking any action, these exceptions bubble up from the Data Access Layer to the Business Logic Layer, then to the ASP.NET page, and finally to the ASP.NET runtime.

웹 응용 프로그램을 구성 하는 방법 및 응용 프로그램을 localhost에서 방문 하는지 여부에 따라 처리 되지 않은 예외로 인해 일반 서버 오류 페이지, 자세한 오류 보고서 또는 사용자에 게 친숙 한 웹 페이지가 표시 될 수 있습니다.Depending on how your web application is configured and whether or not you're visiting the application from localhost, an unhandled exception can result in either a generic server-error page, a detailed error report, or a user-friendly web page. ASP.NET 런타임이 catch 되지 않은 예외에 응답 하는 방법에 대 한 자세한 내용은 ASP.NET의 웹 응용 프로그램 오류 처리customErrors 요소 를 참조 하세요.See Web Application Error Handling in ASP.NET and the customErrors Element for more information on how the ASP.NET runtime responds to an uncaught exception.

그림 6에서는 ProductName 값을 지정 하지 않고 제품 업데이트를 시도할 때 발생 하는 화면을 보여 줍니다.Figure 6 shows the screen encountered when attempting to update a product without specifying the ProductName value. 이는 localhost을 통해 제공 될 때 표시 되는 기본 자세한 오류 보고서입니다.This is the default detailed error report displayed when coming through localhost.

제품 이름을 생략 예외 정보가 표시 됩니다.Omitting the Product's Name Will Display Exception Details

그림 6: 제품 이름을 생략 하면 예외 정보가 표시 됩니다 (전체 크기 이미지를 보려면 클릭).Figure 6: Omitting the Product's Name Will Display Exception Details (Click to view full-size image)

이러한 예외 정보는 응용 프로그램을 테스트할 때 유용 하지만, 최종 사용자에 게 예외를 발생 한 화면에 표시 하는 것은 이상적인 것 보다 낮습니다.While such exception details are helpful when testing an application, presenting an end user with such a screen in the face of an exception is less than ideal. 최종 사용자가 NoNullAllowedException 무엇 인지 또는 왜 발생 했는지 알 수 없습니다.An end user likely doesn't know what a NoNullAllowedException is or why it was caused. 더 나은 방법은 제품 업데이트를 시도 하는 데 문제가 있다는 것을 설명 하는 보다 사용자에 게 친숙 한 메시지를 사용자에 게 제공 하는 것입니다.A better approach is to present the user with a more user-friendly message explaining that there were problems attempting to update the product.

작업을 수행할 때 예외가 발생 하는 경우 ObjectDataSource 및 데이터 웹 컨트롤의 사후 수준 이벤트는이를 감지 하 고 ASP.NET 런타임에 대 한 버블링에서 예외를 취소 하는 수단을 제공 합니다.If an exception occurs when performing the operation, the post-level events in both the ObjectDataSource and the data Web control provide a means to detect it and cancel the exception from bubbling up to the ASP.NET runtime. 이 예제에서는 예외가 발생 했는지 여부를 확인 하 고 레이블 웹 컨트롤에 예외 세부 정보를 표시 하는 GridView의 RowUpdated 이벤트에 대 한 이벤트 처리기를 만들어 보겠습니다.For our example, let's create an event handler for the GridView's RowUpdated event that determines if an exception has fired and, if so, displays the exception details in a Label Web control.

ASP.NET 페이지에 레이블을 추가 하 고 해당 ID 속성을 ExceptionDetails 설정 하 고 Text 속성을 지워 시작 합니다.Start by adding a Label to the ASP.NET page, setting its ID property to ExceptionDetails and clearing out its Text property. 이 메시지에 사용자의 눈동자를 그리려면 CssClass 속성을 이전 자습서의 Styles.css 파일에 추가한 CSS 클래스인 Warning으로 설정 합니다.In order to draw the user's eye to this message, set its CssClass property to Warning, which is a CSS class we added to the Styles.css file in the previous tutorial. 이 CSS 클래스를 통해 레이블의 텍스트가 빨강, 기울임꼴, 굵게, 초대형 글꼴로 표시 됩니다.Recall that this CSS class causes the Label's text to be displayed in a red, italic, bold, extra large font.

페이지에 Label 웹 컨트롤을 추가 Add a Label Web Control to the Page

그림 7: 페이지에 Label 웹 컨트롤 추가 (전체 크기 이미지를 보려면 클릭)Figure 7: Add a Label Web Control to the Page (Click to view full-size image)

예외가 발생 한 직후에이 Label 웹 컨트롤을 표시 하려면 Page_Load 이벤트 처리기에서 Visible 속성을 false로 설정 합니다.Since we want this Label Web control to be visible only immediately after an exception has occurred, set its Visible property to false in the Page_Load event handler:

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    ExceptionDetails.Visible = False
End Sub

이 코드를 사용 하 여 첫 번째 페이지를 방문 하 고 이후에 다시 게시 하면 ExceptionDetails 컨트롤의 Visible 속성이 false으로 설정 됩니다.With this code, on the first page visit and subsequent postbacks the ExceptionDetails control will have its Visible property set to false. GridView의 RowUpdated 이벤트 처리기에서 검색할 수 있는 DAL 또는 BLL 수준 예외의 면에서 ExceptionDetails 컨트롤의 Visible 속성을 true로 설정 합니다.In the face of a DAL- or BLL-level exception, which we can detect in the GridView's RowUpdated event handler, we will set the ExceptionDetails control's Visible property to true. 웹 컨트롤 이벤트 처리기는 페이지 수명 주기의 Page_Load 이벤트 처리기 이후에 발생 하므로 레이블이 표시 됩니다.Since Web control event handlers occur after the Page_Load event handler in the page lifecycle, the Label will be shown. 그러나 다음 포스트백에서 Page_Load 이벤트 처리기는 Visible 속성을 다시 false으로 되돌리고 뷰에서 다시 숨깁니다.However, on the next postback, the Page_Load event handler will revert the Visible property back to false, hiding it from view again.

Note

또는 선언적 구문에서 Visible 속성 false을 할당 하 고 해당 뷰 상태 (EnableViewState 속성을 false로 설정)를 사용 하지 않도록 설정 하 여 Page_Load에서 ExceptionDetails 컨트롤의 Visible 속성을 설정 하는 데 필요한 기능을 제거할 수 있습니다.Alternatively, we could remove the necessity for setting the ExceptionDetails control's Visible property in Page_Load by assigning its Visible property false in the declarative syntax and disabling its view state (setting its EnableViewState property to false). 이후 자습서에서는이 대체 방법을 사용 합니다.We'll use this alternative approach in a future tutorial.

레이블 컨트롤이 추가 되 면 다음 단계는 GridView의 RowUpdated 이벤트에 대 한 이벤트 처리기를 만드는 것입니다.With the Label control added, our next step is to create the event handler for the GridView's RowUpdated event. 디자이너에서 GridView를 선택 하 고 속성 창으로 이동한 후 번개 아이콘을 클릭 하 여 GridView의 이벤트를 나열 합니다.Select the GridView in the Designer, go to the Properties window, and click the lightning bolt icon, listing the GridView's events. 이 자습서의 앞부분에서이 이벤트에 대 한 이벤트 처리기를 만들었으므로 GridView의 RowUpdating 이벤트에 대 한 항목이 이미 있습니다.There should already be an entry there for the GridView's RowUpdating event, as we created an event handler for this event earlier in this tutorial. RowUpdated 이벤트에 대 한 이벤트 처리기도 만듭니다.Create an event handler for the RowUpdated event as well.

GridView의 RowUpdated 이벤트에 대 한 이벤트 처리기 만들기

그림 8: GridView의 RowUpdated 이벤트에 대 한 이벤트 처리기 만들기Figure 8: Create an Event Handler for the GridView's RowUpdated Event

Note

코드 지향 클래스 파일의 맨 위에 있는 드롭다운 목록을 통해 이벤트 처리기를 만들 수도 있습니다.You can also create the event handler through the drop-down lists at the top of the code-behind class file. 왼쪽의 드롭다운 목록에서 GridView를 선택 하 고 오른쪽에 있는 RowUpdated 이벤트를 선택 합니다.Select the GridView from the drop-down list on the left and the RowUpdated event from the one on the right.

이 이벤트 처리기를 만들면 ASP.NET 페이지의 코드 숨김이 클래스에 다음 코드가 추가 됩니다.Creating this event handler will add the following code to the ASP.NET page's code-behind class:

Protected Sub GridView1_RowUpdated(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs) _
    Handles GridView1.RowUpdated
End Sub

이 이벤트 처리기의 두 번째 입력 매개 변수는 예외를 처리 하는 데 필요한 세 가지 속성을 포함 하는 GridViewUpdatedEventArgs형식의 개체입니다.This event handler's second input parameter is an object of type GridViewUpdatedEventArgs, which has three properties of interest for handling exceptions:

  • throw 된 예외에 대 한 참조를 Exception 합니다. 예외가 throw 되지 않은 경우이 속성의 값은 nullException a reference to the thrown exception; if no exception has been thrown, this property will have a value of null
  • 예외가 RowUpdated 이벤트 처리기에서 처리 되었는지 여부를 나타내는 부울 값을 ExceptionHandled 합니다. false (기본값) 이면 예외가 다시 throw 되 고 ASP.NET 런타임으로 배치 됩니다.ExceptionHandled a Boolean value that indicates whether or not the exception was handled in the RowUpdated event handler; if false (the default), the exception is re-thrown, percolating up to the ASP.NET runtime
  • true로 설정 하면 편집 된 GridView 행이 편집 모드에 남아 KeepInEditMode. false (기본값) 이면 GridView 행이 읽기 전용 모드로 돌아갑니다.KeepInEditMode if set to true the edited GridView row remains in edit mode; if false (the default), the GridView row reverts back to its read-only mode

그런 다음 코드는 Exception null되지 않았는지 확인 해야 합니다. 즉, 작업을 수행 하는 동안 예외가 발생 했음을 확인 해야 합니다.Our code, then, should check to see if Exception is not null, meaning that an exception was raised while performing the operation. 이 경우 다음과 같은 작업을 수행 합니다.If this is the case, we want to:

  • ExceptionDetails 레이블에 사용자에 게 친숙 한 메시지 표시Display a user-friendly message in the ExceptionDetails Label
  • 예외가 처리 되었음을 표시 합니다.Indicate that the exception was handled
  • 편집 모드에서 GridView 행 유지Keep the GridView row in edit mode

이러한 목표를 달성 하는 코드는 다음과 같습니다.This following code accomplishes these objectives:

Protected Sub GridView1_RowUpdated(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewUpdatedEventArgs) _
    Handles GridView1.RowUpdated
    If e.Exception IsNot Nothing Then
        ExceptionDetails.Visible = True
        ExceptionDetails.Text = "There was a problem updating the product. "
        If e.Exception.InnerException IsNot Nothing Then
            Dim inner As Exception = e.Exception.InnerException
            If TypeOf inner Is System.Data.Common.DbException Then
                ExceptionDetails.Text &= _
                "Our database is currently experiencing problems." & _
                "Please try again later."
            ElseIf TypeOf inner _
             Is System.Data.NoNullAllowedException Then
                ExceptionDetails.Text += _
                    "There are one or more required fields that are missing."
            ElseIf TypeOf inner Is ArgumentException Then
                Dim paramName As String = CType(inner, ArgumentException).ParamName
                ExceptionDetails.Text &= _
                    String.Concat("The ", paramName, " value is illegal.")
            ElseIf TypeOf inner Is ApplicationException Then
                ExceptionDetails.Text += inner.Message
            End If
        End If
        e.ExceptionHandled = True
        e.KeepInEditMode = True
    End If
End Sub

이 이벤트 처리기는 e.Exception null되었는지 확인 하 여 시작 합니다.This event handler begins by checking to see if e.Exception is null. 그렇지 않은 경우 ExceptionDetails 레이블의 Visible 속성은 true로 설정 되 고 해당 Text 속성은 "제품을 업데이트 하는 데 문제가 있습니다."로 설정 됩니다.If it's not, the ExceptionDetails Label's Visible property is set to true and its Text property to "There was a problem updating the product." Throw 된 실제 예외의 세부 정보는 e.Exception 개체의 InnerException 속성에 있습니다.The details of the actual exception that was thrown reside in the e.Exception object's InnerException property. 이 내부 예외를 검사 하 고 특정 형식이 면 ExceptionDetails 레이블의 Text 속성에 추가 유용한 메시지가 추가 됩니다.This inner exception is examined and, if it is of a particular type, an additional, helpful message is appended to the ExceptionDetails Label's Text property. 마지막으로 ExceptionHandledKeepInEditMode 속성이 모두 true로 설정 됩니다.Lastly, the ExceptionHandled and KeepInEditMode properties are both set to true.

그림 9에서는 제품 이름을 생략 하는 경우이 페이지의 스크린샷 그림 10에서는 잘못 된 UnitPrice 값 (-50)을 입력할 때의 결과를 보여 줍니다.Figure 9 shows a screen shot of this page when omitting the name of the product; Figure 10 shows the results when entering an illegal UnitPrice value (-50).

ProductName BoundField는 값을 포함 해야 합니다.The ProductName BoundField Must Contain a Value

그림 9: ProductName BoundField는 값을 포함 해야 합니다 (전체 크기 이미지를 보려면 클릭).Figure 9: The ProductName BoundField Must Contain a Value (Click to view full-size image)

음수 UnitPrice 값은 사용할 수 없습니다.Negative UnitPrice Values are Not Allowed

그림 10: 음수 UnitPrice 값이 허용 되지 않음 (전체 크기 이미지를 보려면 클릭)Figure 10: Negative UnitPrice Values are Not Allowed (Click to view full-size image)

e.ExceptionHandled 속성을 true로 설정 하면 RowUpdated 이벤트 처리기에서 예외를 처리 했음을 나타냅니다.By setting the e.ExceptionHandled property to true, the RowUpdated event handler has indicated that it has handled the exception. 따라서 예외는 ASP.NET 런타임으로 전파 되지 않습니다.Therefore, the exception won't propagate up to the ASP.NET runtime.

Note

그림 9와 10은 잘못 된 사용자 입력으로 인해 발생 하는 예외를 처리 하는 정상적인 방법을 보여 줍니다.Figures 9 and 10 show a graceful way to handle exceptions raised due to invalid user input. ASP.NET 페이지는 ProductsBLL 클래스의 UpdateProduct 메서드를 호출 하기 전에 사용자 입력이 올바른지 확인 해야 하기 때문에 이러한 잘못 된 입력은 처음에는 비즈니스 논리 계층에 도달 하지 않습니다.Ideally, though, such invalid input will never reach the Business Logic Layer in the first place, as the ASP.NET page should ensure that the user's inputs are valid before invoking the ProductsBLL class's UpdateProduct method. 다음 자습서에서는 편집 및 삽입 인터페이스에 유효성 검사 컨트롤을 추가 하 여 비즈니스 논리 계층에 제출 된 데이터가 비즈니스 규칙을 따르는지 확인 하는 방법을 알아봅니다.In our next tutorial we'll see how to add validation controls to the editing and inserting interfaces to ensure that the data submitted to the Business Logic Layer conforms to the business rules. 유효성 검사 컨트롤은 사용자가 제공 하는 데이터가 유효 해질 때까지 UpdateProduct 메서드 호출을 방지할 뿐만 아니라 데이터 입력 문제를 식별 하는 데 더 유용한 사용자 환경을 제공 합니다.The validation controls not only prevent the invocation of the UpdateProduct method until the user-supplied data is valid, but also provide a more informative user experience for identifying data entry problems.

3 단계: BLL 수준 예외를 정상적으로 처리Step 3: Gracefully Handling BLL-Level Exceptions

데이터를 삽입, 업데이트 또는 삭제 하는 경우 데이터 액세스 계층이 데이터 관련 오류 발생 시 예외를 throw 할 수 있습니다.When inserting, updating, or deleting data, the Data Access Layer may throw an exception in the face of a data-related error. 데이터베이스가 오프 라인 이거나, 필요한 데이터베이스 테이블 열에 값이 지정 되지 않았거나, 테이블 수준 제약 조건이 위반 되었을 수 있습니다.The database may be offline, a required database table column might not have had a value specified, or a table-level constraint may have been violated. 비즈니스 논리 계층에서는 엄격한 데이터 관련 예외 외에도 예외를 사용 하 여 비즈니스 규칙이 위반 된 시기를 나타낼 수 있습니다.In addition to strictly data-related exceptions, the Business Logic Layer can use exceptions to indicate when business rules have been violated. 예를 들어 비즈니스 논리 계층 만들기 자습서에서 원래 UpdateProduct 오버 로드에 비즈니스 규칙 검사를 추가 했습니다.In the Creating a Business Logic Layer tutorial, for example, we added a business rule check to the original UpdateProduct overload. 특히, 사용자가 제품을 단종 된 것으로 표시 한 경우에는 해당 공급 업체가 제공 하는 제품이 아닌 제품만 필요 합니다.Specifically, if the user was marking a product as discontinued, we required that the product not be the only one provided by its supplier. 이 조건을 위반 하는 경우 ApplicationException throw 됩니다.If this condition was violated, an ApplicationException was thrown.

이 자습서에서 만든 UpdateProduct 오버 로드의 경우 UnitPrice 필드가 원래 UnitPrice 값의 두 배가 넘는 새 값으로 설정 되는 것을 금지 하는 비즈니스 규칙을 추가 해 보겠습니다.For the UpdateProduct overload created in this tutorial, let's add a business rule that prohibits the UnitPrice field from being set to a new value that's more than twice the original UnitPrice value. 이를 수행 하려면 UpdateProduct 오버 로드를 조정 하 여이 검사를 수행 하 고 규칙을 위반 하는 경우 ApplicationException을 throw 합니다.To accomplish this, adjust the UpdateProduct overload so that it performs this check and throws an ApplicationException if the rule is violated. 업데이트 된 메서드는 다음과 같습니다.The updated method follows:

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, True)> _
    Public Function UpdateProduct(ByVal productName As String, _
    ByVal unitPrice As Nullable(Of Decimal), ByVal unitsInStock As Nullable(Of Short), _
    ByVal 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 unitPrice.HasValue AndAlso Not product.IsUnitPriceNull() Then
        If unitPrice > product.UnitPrice * 2 Then
            Throw New ApplicationException( _
                "When updating a product price," & _
                " the new price cannot exceed twice the original price.")
        End If
    End If
    product.ProductName = productName
    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
    Dim rowsAffected As Integer = Adapter.Update(product)
    Return rowsAffected = 1
End Function

이러한 변경으로 인해 기존 가격의 두 배가 넘는 가격 업데이트는 ApplicationException을 throw 합니다.With this change, any price update that is more than twice the existing price will cause an ApplicationException to be thrown. DAL에서 발생 한 예외와 마찬가지로,이 ApplicationException BLL에서 발생 하는이를 검색 하 고 GridView의 RowUpdated 이벤트 처리기에서 처리할 수 있습니다.Just like the exception raised from the DAL, this BLL-raised ApplicationException can be detected and handled in the GridView's RowUpdated event handler. 실제로 작성 된 RowUpdated 이벤트 처리기의 코드는이 예외를 올바르게 검색 하 고 ApplicationExceptionMessage 속성 값을 표시 합니다.In fact, the RowUpdated event handler's code, as written, will correctly detect this exception and display the ApplicationException's Message property value. 그림 11은 사용자가 Chai의 가격을 $50.00로 업데이트 하려고 시도 하는 경우의 스크린샷 ($19.95의 현재 가격의 2 배 이상)을 보여 줍니다.Figure 11 shows a screen shot when a user attempts to update the price of Chai to $50.00, which is more than double its current price of $19.95.

비즈니스 규칙이 가격을 허용 하지 않는 경우 제품 가격을 2 배 이상으로 합니다.The Business Rules Disallow Price Increases That More Than Double a Product's Price

그림 11: 기간을 허용 하지 않는 비즈니스 규칙은 제품의 가격을 두 배로 늘리는 경우 (전체 크기 이미지를 보려면 클릭)Figure 11: The Business Rules Disallow Price Increases That More Than Double a Product's Price (Click to view full-size image)

Note

비즈니스 논리 규칙은 UpdateProduct 메서드 오버 로드 및 일반적인 메서드로 리팩터링 하는 것이 가장 좋습니다.Ideally our business logic rules would be refactored out of the UpdateProduct method overloads and into a common method. 이는 판독기의 연습으로 남아 있습니다.This is left as an exercise for the reader.

요약Summary

삽입, 업데이트 및 삭제 작업 중에는 데이터 웹 컨트롤과 ObjectDataSource가 모두 실제 작업을 bookend 하는 사전 및 사후 수준 이벤트를 발생 시킵니다.During inserting, updating, and deleting operations, both the data Web control and the ObjectDataSource involved fire pre- and post-level events that bookend the actual operation. 이 자습서와 앞에서 살펴본 것 처럼 편집 가능한 GridView를 사용 하 여 작업 하는 경우 GridView의 RowUpdating 이벤트가 발생 하 고 그 다음에 ObjectDataSource의 Updating 이벤트가 발생 합니다 .이 시점에서 ObjectDataSource의 내부 개체에 대 한 update 명령이 수행 됩니다.As we saw in this tutorial and the preceding one, when working with an editable GridView the GridView's RowUpdating event fires, followed by the ObjectDataSource's Updating event, at which point the update command is made to the ObjectDataSource's underlying object. 작업이 완료 되 면 ObjectDataSource의 Updated 이벤트가 실행 된 다음 GridView의 RowUpdated 이벤트가 발생 합니다.After the operation has completed, the ObjectDataSource's Updated event fires, followed by the GridView's RowUpdated event.

작업 결과를 검사 하 고 응답 하기 위해 사후 수준 이벤트에 대 한 입력 매개 변수를 사용자 지정 하기 위해 사전 수준 이벤트에 대 한 이벤트 처리기를 만들 수 있습니다.We can create event handlers for the pre-level events in order to customize the input parameters or for the post-level events in order to inspect and respond to the operation's results. 사후 수준 이벤트 처리기는 작업 중에 예외가 발생 했는지 여부를 검색 하는 데 가장 일반적으로 사용 됩니다.Post-level event handlers are most commonly used to detect whether an exception occurred during the operation. 예외가 발생 하는 경우 이러한 사후 수준 이벤트 처리기는 선택적으로 예외를 처리할 수 있습니다.In the face of an exception, these post-level event handlers can optionally handle the exception on their own. 이 자습서에서는 친숙 한 오류 메시지를 표시 하 여 이러한 예외를 처리 하는 방법을 살펴보았습니다.In this tutorial we saw how to handle such an exception by displaying a friendly error message.

다음 자습서에서는 데이터 서식 문제 (예: 음수 UnitPrice입력)에서 발생 하는 예외의 가능성을 완화 하는 방법을 알아봅니다.In the next tutorial we'll see how to lessen the likelihood of exceptions arising from data formatting issues (such as entering a negative UnitPrice). 특히 편집 및 삽입 인터페이스에 유효성 검사 컨트롤을 추가 하는 방법을 살펴보겠습니다.Specifically, we'll look at how to add validation controls to the editing and inserting interfaces.

행복 한 프로그래밍Happy Programming!

저자 정보About the Author

Scott Mitchell(7 개의 ASP/ASP. NET books 및 4GuysFromRolla.com창립자)은 1998부터 Microsoft 웹 기술을 사용 하 여 작업 했습니다.Scott Mitchell, author of seven ASP/ASP.NET books and founder of 4GuysFromRolla.com, has been working with Microsoft Web technologies since 1998. Scott은 독립 컨설턴트, 강사 및 기록기로 작동 합니다.Scott works as an independent consultant, trainer, and writer. 최신 책은 24 시간 이내에 ASP.NET 2.0을 sams teach yourself것입니다.His latest book is Sams Teach Yourself ASP.NET 2.0 in 24 Hours. mitchell@4GuysFromRolla.com에 도달할 수 있습니다 .He can be reached at mitchell@4GuysFromRolla.com. 또는 블로그를 통해 http://ScottOnWriting.NET에서 찾을 수 있습니다.or via his blog, which can be found at http://ScottOnWriting.NET.

특별히 감사 합니다.Special Thanks To

이 자습서 시리즈는 많은 유용한 검토자가 검토 했습니다.This tutorial series was reviewed by many helpful reviewers. 이 자습서의 리드 검토자는 Liz Shulok입니다.Lead reviewer for this tutorial was Liz Shulok. 예정 된 MSDN 문서를 검토 하는 데 관심이 있나요?Interested in reviewing my upcoming MSDN articles? 그렇다면mitchell@4GuysFromRolla.com에서 줄을 삭제 합니다.If so, drop me a line at mitchell@4GuysFromRolla.com.