Megosztás a következőn keresztül:


BLL- és DAL-szintű kivételek (VB) kezelése

által Scott Mitchell

PDF letöltése

Ebben az oktatóanyagban bemutatjuk, hogyan kezelhetők a szerkeszthető DataList frissítési munkafolyamata során felmerülő kivételek.

Bevezetés

Az Adatok szerkesztésének és törlésének áttekintésében a DataList oktatóanyagban létrehoztunk egy DataListet, amely egyszerű szerkesztési és törlési képességeket kínál. Bár teljesen működőképes volt, alig volt felhasználóbarát, mivel a szerkesztési vagy törlési folyamat során előforduló hibák nem kezelt kivételt eredményeztek. Ha például kihagyja a termék nevét, vagy ha szerkeszt egy terméket, akkor a Nagyon megfizethető!árérték megadása kivételt jelent. Mivel ez a kivétel nincs kezelve a kódban, felbuborékol az ASP.NET futtatókörnyezethez, amely ezután megjeleníti a kivétel részleteit a weblapon.

Ahogy az ASP.NET lapon a BLL- és DAL-Level kivételek kezelése című oktatóanyagban láttuk, ha az üzleti logika vagy az adatelérési rétegek mélységéből kivétel keletkezik, a kivétel részletei visszakerülnek az ObjectDataSource-ba, majd a GridView-ba. Láttuk, hogyan kell ezeket a kivételeket elegánsan kezelni, úgy, hogy Updated vagy RowUpdated eseménykezelőket hozunk létre az ObjectDataSource-hoz vagy a GridView-hoz, ellenőrizzük a kivételt, és jelezzük, hogy a kivételt kezeltük.

A DataList-oktatóanyagok azonban nem az ObjectDataSource-t használják az adatok frissítéséhez és törléséhez. Ehelyett közvetlenül a BLL ellen dolgozunk. A BLL-ből vagy DAL-ból származó kivételek észleléséhez a kivételkezelési kódot a ASP.NET lap mögötti kódban kell implementálni. Ebben az oktatóanyagban azt fogjuk látni, hogyan kezelhetők a szerkeszthető DataList frissítési munkafolyamatai során felmerülő kivételek.

Megjegyzés:

Az Adatok szerkesztésének és törlésének áttekintése a DataList oktatóanyagban az adatok DataList-ből való szerkesztésének és törlésének különböző technikáiról volt szó, néhány módszer, amely az ObjectDataSource használatával történt a frissítéshez és a törléshez. Ha ezeket a technikákat alkalmazza, a BLL-ből vagy a DAL-ból származó kivételeket az ObjectDataSource-on Updated vagy Deleted az eseménykezelőn keresztül kezelheti.

1. lépés: Szerkeszthető adatlista létrehozása

Mielőtt a frissítési munkafolyamat során előforduló kivételek kezelésével foglalkoznánk, először hozzunk létre egy szerkeszthető DataListet. Nyissa meg a ErrorHandling.aspx lapot a EditDeleteDataList mappában, vegyen fel egy DataListet a Tervezőbe, állítsa be a tulajdonságát IDProducts, és adjon hozzá egy új ObjectDataSource nevű ProductsDataSourceobjektumot. Konfigurálja az ObjectDataSource-t úgy, hogy az ProductsBLL osztály s GetProducts() metódusát használja a rekordok kiválasztásához; állítsa az INSERT, UPDATE és DELETE fül legördülő listáit a (Nincs) értékre.

Adja vissza a termékinformációkat a GetProducts() metódussal

1. ábra: Adja vissza a termékinformációkat a GetProducts() metódus használatával (kattintson ide a teljes méretű kép megtekintéséhez)

Az ObjectDataSource varázsló befejezése után a Visual Studio automatikusan létrehoz egy ItemTemplate adatlistát. Cserélje le ezt egy olyanra ItemTemplate , amely megjeleníti az egyes termékek nevét és árát, és tartalmaz egy Szerkesztés gombot. Ezután hozzon létre egy EditItemTemplate-t, amely tartalmaz egy TextBox webvezérlőt a név és az ár megadásához, valamint Frissítés és Mégse gombokat. Végül állítsa a DataList tulajdonságát RepeatColumns 2-re.

A módosítások után a lap deklaratív korrektúrája az alábbihoz hasonlóan fog kinézni. Győződjön meg róla, hogy a Szerkesztés, Mégse és Frissítés gombok tulajdonságai be vannak állítva Szerkesztésre, Mégse-re és Frissítésre.

<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>

Megjegyzés:

Ebben az oktatóanyagban engedélyezni kell a DataList nézetállapotát.

Szánjon egy kis időt az előrehaladás megtekintésére egy böngészőben (lásd a 2. ábrát).

Minden termék tartalmaz szerkesztési gombot

2. ábra: Minden termék tartalmaz szerkesztési gombot (kattintson ide a teljes méretű kép megtekintéséhez)

A Szerkesztés gomb jelenleg csak visszatöltést okoz, de még nem teszi szerkeszthetővé a terméket. A szerkesztés engedélyezéséhez eseménykezelőket kell létrehoznunk a DataList s EditCommandés CancelCommandUpdateCommand az események számára. Az EditCommand és CancelCommand események egyszerűen frissítik a DataList EditItemIndex tulajdonságát, és újrahozzárendelik az adatokat a DataListhez.

Protected Sub Products_EditCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.EditCommand
    ' 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()
End Sub
Protected Sub Products_CancelCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.CancelCommand
    ' Set the DataList's EditItemIndex property to -1
    Products.EditItemIndex = -1
    ' Rebind the data to the DataList
    Products.DataBind()
End Sub

Az UpdateCommand eseménykezelő kicsit összetettebb. Be kell olvasnia a szerkesztett terméket ProductID a DataKeys gyűjteményből, a termék nevével és árával együtt a EditItemTemplate szövegmezőkből. Ezután meg kell hívnia az ProductsBLL osztály UpdateProduct metódusát, mielőtt visszaállítaná a DataListet az eredeti, szerkesztés előtti állapotába.

Egyelőre csak ugyanazt a kódot használjuk az eseménykezelőtől a UpdateCommandDataList oktatóanyag adatainak szerkesztésének és törlésének áttekintésében . Hozzáadjuk a kódot a 2. lépésben szereplő kivételek kecses kezeléséhez.

Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.UpdateCommand
    ' Read in the ProductID from the DataKeys collection
    Dim productID As Integer = Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
    ' Read in the product name and price values
    Dim productName As TextBox = CType(e.Item.FindControl("ProductName"), TextBox)
    Dim unitPrice As TextBox = CType(e.Item.FindControl("UnitPrice"), TextBox)
    Dim productNameValue As String = Nothing
    If productName.Text.Trim().Length > 0 Then
        productNameValue = productName.Text.Trim()
    End If
    Dim unitPriceValue As Nullable(Of Decimal) = Nothing
    If unitPrice.Text.Trim().Length > 0 Then
        unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(), _
                         System.Globalization.NumberStyles.Currency)
    End If
    ' Call the ProductsBLL's UpdateProduct method...
    Dim productsAPI As New ProductsBLL()
    productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID)
    ' Revert the DataList back to its pre-editing state
    Products.EditItemIndex = -1
    Products.DataBind()
End Sub

Érvénytelen bemenet esetén, amely nem megfelelően formázott egységár formájában is lehetséges, a rendszer kivételt emel ki egy illegális egységár-érték (például -5,00 USD) vagy a termék nevének kihagyása miatt. Mivel az UpdateCommand eseménykezelő jelenleg nem tartalmaz kivételkezelési kódot, a kivétel felborul a ASP.NET futtatókörnyezetig, ahol az megjelenik a végfelhasználó számára (lásd a 3. ábrát).

Kezeletlen kivétel esetén a végfelhasználó hibaüzenetet jelenít meg

3. ábra: Kezeletlen kivétel esetén a végfelhasználó hibaüzenetet jelenít meg

2. lépés: Kivételek türelmes kezelése az UpdateCommand eseménykezelőben

A frissítési munkafolyamat során kivételek léphetnek fel az UpdateCommand eseménykezelőben, a BLL-ben vagy a DAL-ban. Ha például egy felhasználó túl drága árat ad meg, az Decimal.Parse eseménykezelőben lévő UpdateCommand utasítás kivételt FormatException fog eredményezni. Ha a felhasználó kihagyja a termék nevét, vagy ha az ár negatív értékkel rendelkezik, a DAL kivételt fog eredményezni.

Kivétel esetén egy tájékoztató üzenetet szeretnénk megjeleníteni a lapon belül. Adjon hozzá egy Címke webvezérlőt ahhoz a laphoz, amelynek ID be van állítva ExceptionDetails-re. A Címke szövegét úgy konfigurálhatja, hogy piros, extra nagy, félkövér és dőlt betűtípusban jelenjen meg, ha a tulajdonságot CssClass a Warning fájlban meghatározott Styles.css CSS-osztályhoz rendeli.

Hiba esetén csak egyszer szeretnénk megjeleníteni a címkét. Ez azt jelzi, hogy a későbbi visszalépések esetén a címke figyelmeztető üzenetének el kell tűnnie. Ezt úgy teheti meg, hogy törli a Label Text tulajdonságát, vagy az Visible eseménykezelőben beállítja a tulajdonságát FalsePage_Load értékre (ahogyan azt a ASP.NET oldalakon BLL- és DAL-Level kivételek kezelése című oktatóanyagban tettük), vagy a Label nézetállapot támogatásának letiltásával. Használjuk az utóbbi lehetőséget.

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

Kivétel felmerülésekor a kivétel részleteit a ExceptionDetails Címke vezérlőelem Text tulajdonságához rendeljük. Mivel a nézet állapota le van tiltva, a későbbi visszavételek során a Text tulajdonság programozott módosításai elvesznek, és visszaállnak az alapértelmezett szövegre (egy üres sztringre), így elrejtik a figyelmeztető üzenetet.

Annak megállapításához, hogy mikor jelentkezett hiba a lapon egy hasznos üzenet megjelenítéséhez, fel kell venni egy blokkot Try ... Catch az UpdateCommand eseménykezelőbe. A Try rész olyan kódot tartalmaz, amely kivételhez vezethet, míg a Catch blokk egy kivétellel szemben végrehajtott kódot tartalmaz. A blokkról további információt a .NET-keretrendszer dokumentációjának Try ... Catch című szakaszában talál.

Protected Sub Products_UpdateCommand(source As Object, e As DataListCommandEventArgs) _
    Handles Products.UpdateCommand
    ' Handle any exceptions raised during the editing process
    Try
        ' Read in the ProductID from the DataKeys collection
        Dim productID As Integer = _
            Convert.ToInt32(Products.DataKeys(e.Item.ItemIndex))
        ... Some code omitted for brevity ...
    Catch ex As Exception
        ' TODO: Display information about the exception in ExceptionDetails
    End Try
End Sub

Ha a Try blokkon belüli kód bármilyen típusú kivételt hoz létre, a Catch blokk kódja elkezd végrehajtódni. A kidobottDbExceptionNoNullAllowedExceptionArgumentException, stb. kivétel típusa attól függ, hogy pontosan mi okozza a hibát. Ha probléma merül fel az adatbázis szintjén, a rendszer egy DbException hibát fog dobni. Ha érvénytelen értéket adnak meg a UnitPrice, UnitsInStock, UnitsOnOrder vagy ReorderLevel mezőkhöz, akkor ArgumentException kivétel váltódik ki, mivel kódot adtunk hozzá a mezőértékek ellenőrzéséhez az ProductsDataTable osztályban (lásd az Üzleti logikai réteg létrehozása oktatóanyagot).

Hasznosabb magyarázatot adhatunk a végfelhasználónak, ha az üzenet szövegét a kifogott kivétel típusára alapozzuk. Az alábbi kód, amelyet régebben, szinte azonos formában használtak a BLL- és DAL-Level Kivételek kezelése ASP.NET oldalon bemutatóban, ezt a részletezési szintet nyújtja.

Private Sub DisplayExceptionDetails(ByVal ex As Exception)
    ' Display a user-friendly message
    ExceptionDetails.Text = "There was a problem updating the product. "
    If TypeOf ex Is System.Data.Common.DbException Then
        ExceptionDetails.Text += "Our database is currently experiencing problems." + _
                                 "Please try again later."
    ElseIf TypeOf ex Is System.Data.NoNullAllowedException Then
        ExceptionDetails.Text+="There are one or more required fields that are missing."
    ElseIf TypeOf ex Is ArgumentException Then
        Dim paramName As String = CType(ex, ArgumentException).ParamName
        ExceptionDetails.Text+=String.Concat("The ", paramName, " value is illegal.")
    ElseIf TypeOf ex Is ApplicationException Then
        ExceptionDetails.Text += ex.Message
    End If
End Sub

Az oktatóanyag elvégzéséhez egyszerűen hívja meg a DisplayExceptionDetails metódust a Catch blokkon belül, átadva a fogott Exception példányt (ex).

A blokk helyén egy Try ... Catch informatívabb hibaüzenet jelenik meg a felhasználók számára, ahogy a 4. és az 5. ábra is mutatja. Vegye figyelembe, hogy kivétel esetén a DataList szerkesztési módban marad. Ennek az az oka, hogy a kivétel bekövetkezése után a rendszer azonnal átirányítja a vezérlőfolyamatot a Catch blokkba, megkerülve azt a kódot, amely a DataListet az előszerkesztési állapotba adja vissza.

Hibaüzenet jelenik meg, ha egy felhasználó kihagy egy kötelező mezőt

4. ábra: Hibaüzenet jelenik meg, ha egy felhasználó kihagy egy kötelező mezőt (ide kattintva megtekintheti a teljes méretű képet)

Negatív ár megadásakor hibaüzenet jelenik meg

5. ábra: Negatív ár megadásakor hibaüzenet jelenik meg (ide kattintva megtekintheti a teljes méretű képet)

Összefoglalás

A GridView és az ObjectDataSource olyan posztszintű eseménykezelőket biztosít, amelyek információkat tartalmaznak a frissítési és törlési munkafolyamat során felmerült kivételekről, valamint olyan tulajdonságokat, amelyek megadhatók annak jelzésére, hogy a kivételt kezelték-e. Ezek a funkciók azonban nem érhetők el a DataList használata és a BLL közvetlen használata esetén. Ehelyett mi vagyunk a felelősek a kivételkezelés megvalósításáért.

Ebben az oktatóanyagban azt láttuk, hogyan adhat hozzá kivételkezelést egy szerkeszthető DataList-frissítési munkafolyamathoz úgy, hogy egy blokkot Try ... Catch ad hozzá az UpdateCommand eseménykezelőhöz. Ha a frissítési munkafolyamat során kivétel keletkezik, a Catch blokk kódjának végrehajtása hasznos információkat jelenít meg a ExceptionDetails címkében.

Ezen a ponton a DataList nem törekszik arra, hogy megakadályozza a kivételek bekövetkezését. Annak ellenére, hogy tudjuk, hogy a negatív ár kivételt eredményez, még nem adtunk hozzá semmilyen funkciót, hogy proaktív módon megakadályozzuk, hogy egy felhasználó ilyen érvénytelen bemenetet adjon meg. A következő oktatóanyagban bemutatjuk, hogyan csökkentheti az érvénytelen felhasználói bemenetek által okozott kivételeket azáltal, hogy érvényesítési vezérlőket ad hozzá a EditItemTemplate.

Boldog programozást!

További olvasás

Az oktatóanyagban tárgyalt témakörökről az alábbi forrásokban talál további információt:

Tudnivalók a szerzőről

Scott Mitchell, hét ASP/ASP.NET-könyv szerzője és a 4GuysFromRolla.com alapítója, 1998 óta dolgozik a Microsoft webtechnológiáival. Scott független tanácsadóként, edzőként és íróként dolgozik. Legújabb könyve Sams Tanuld meg ASP.NET 2.0 24 óra alatt. Ő itt elérhető mitchell@4GuysFromRolla.com.

Külön köszönet

Ezt az oktatóanyag-sorozatot sok hasznos véleményező áttekintette. Az oktatóanyag vezető véleményezője Ken Pespisa volt. Szeretné áttekinteni a közelgő MSDN-cikkeimet? Ha igen, írj egy sort a mitchell@4GuysFromRolla.com-ra.