Sdílet prostřednictvím


Dávkové vkládání (VB)

od Scotta Mitchella

Stáhnout PDF

Zjistěte, jak do jedné operace vložit více záznamů databáze. Ve vrstvě uživatelského rozhraní rozšiřujeme Objekt GridView tak, aby uživatel mohl zadat více nových záznamů. Ve vrstvě přístupu k datům obalujeme několik vložek v rámci transakce, aby bylo zajištěno, že všechny vložky úspěšně proběhnou nebo budou všechny vráceny zpět.

Úvod

V kurzu Dávkové aktualizace jsme se zaměřili na úpravu ovládacího prvku GridView tak, aby rozhraní umožňovalo editaci více záznamů. Uživatel, který stránku navštíví, může provést řadu změn a pak jediným kliknutím na tlačítko provést dávkovou aktualizaci. V situacích, kdy uživatelé často aktualizují mnoho záznamů na jednom místě, může takové rozhraní ušetřit bezpočet kliknutí a přepínačů kontextu myši na myš ve srovnání s výchozími funkcemi úprav pro jednotlivé řádky, které byly poprvé prozkoumány v kurzu Přehled vkládání, aktualizace a odstraňování dat .

Tento koncept lze použít také při přidávání záznamů. Představte si, že zde v Northwind Traders obvykle dostáváme zásilky od dodavatelů, kteří obsahují řadu produktů pro určitou kategorii. Jako příklad můžeme obdržet dodávku šesti různých produktů čaje a kávy od společnosti Tokyo Traders. Pokud uživatel zadá šest produktů postupně prostřednictvím ovládacího prvku DetailsView, bude muset vybrat mnoho stejných hodnot znovu: bude muset vybrat stejnou kategorii (nápoje), stejného dodavatele (Tokyo Traders), stejnou ukončenou hodnotu (False) a stejné jednotky pro hodnotu objednávky (0). Toto opakované zadávání dat není jenom časově náročné, ale náchylné k chybám.

S trochou práce můžeme vytvořit dávkové vkládání rozhraní, které uživateli umožňuje vybrat dodavatele a kategorii jednou, zadat řadu názvů produktů a jednotkových cen a poté kliknutím na tlačítko přidat nové produkty do databáze (viz obrázek 1). Při přidání každého produktu jsou jeho ProductName a UnitPrice datová pole přiřazena hodnotám zadaným v textových polích, zatímco jeho CategoryID a SupplierID hodnoty jsou přiřazeny hodnoty z rozevíracích seznamů v horní části formuláře. Hodnoty Discontinued a UnitsOnOrder jsou nastaveny na pevně zakódované hodnoty False a 0, respektive.

Rozhraní dávkového vkládání

Obrázek 1: Rozhraní dávkového vkládání (kliknutím zobrazíte obrázek s plnou velikostí)

V tomto kurzu vytvoříme stránku, která implementuje rozhraní dávkového vkládání znázorněné na obrázku 1. Stejně jako v předchozích dvou tutoriálech zabalíme vložení do rozsahu transakce, abychom zajistili atomicitu. Pojďme začít!

Krok 1: Vytvoření rozhraní pro zobrazení

Tento kurz se skládá z jedné stránky rozdělené do dvou oblastí: oblasti zobrazení a oblasti vložení. Rozhraní pro zobrazení, které vytvoříme v tomto kroku, zobrazuje produkty v GridView a obsahuje tlačítko s názvem Zpracovat zásilku produktu. Po kliknutí na toto tlačítko se rozhraní pro zobrazení nahradí vloženým rozhraním, které je znázorněno na obrázku 1. Rozhraní zobrazení se vrátí po kliknutí na tlačítko Přidat produkty z dodávky nebo Zrušit. V kroku 2 vytvoříme vložené rozhraní.

Při vytváření stránky se dvěma rozhraními je vždy viditelné pouze jedno z nich, obvykle se každé rozhraní umístí do webového ovládacího prvku Panel, který slouží jako kontejner pro jiné ovládací prvky. Naše stránka proto bude mít dva ovládací prvky panelu jeden pro každé rozhraní.

Začněte otevřením BatchInsert.aspx stránky ve BatchData složce a přetažením panelu z panelu nástrojů do Návrháře (viz obrázek 2). Nastavte vlastnost panelu s ID na DisplayInterface hodnotu. Při přidávání panelu do Návrháře jsou jeho Height a Width vlastnosti nastaveny na 50px a 125px v uvedeném pořadí. Vymažte tyto hodnoty vlastností z okna Vlastnosti.

Přetažení panelu ze sady nástrojů do Návrháře

Obrázek 2: Přetažení panelu z panelu nástrojů do Návrháře (kliknutím zobrazíte obrázek v plné velikosti)

Poté přetáhněte ovládací prvek Button a GridView do panelu. Nastavte vlastnost tlačítka ID na ProcessShipment a jeho vlastnost Text na Zpracování dodávky produktu. Nastavte vlastnost GridView ID na ProductsGrid a ze smart tagu ji navázejte na nový ObjectDataSource pojmenovaný ProductsDataSource. Nakonfigurujte ObjectDataSource tak, aby získával data z metody třídy ProductsBLLGetProducts. Vzhledem k tomu, že tento Objekt GridView slouží pouze k zobrazení dat, nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (Žádné). Kliknutím na tlačítko Dokončit dokončete průvodce konfigurací zdroje dat.

Zobrazení dat vrácených z metody GetProducts třídy ProductsBLL

Obrázek 3: Zobrazení dat vrácených metodou ProductsBLL třídy GetProducts (kliknutím zobrazíte obrázek v plné velikosti)

Nastavte Drop-Down seznamy na kartách UPDATE, INSERT a DELETE na (Žádné).

Obrázek 4: Nastavení Drop-Down seznamů na kartách UPDATE, INSERT a DELETE na (Žádné) (Kliknutím zobrazíte obrázek v plné velikosti)

Po dokončení průvodce nástrojem ObjectDataSource Visual Studio přidá BoundFields a CheckBoxField pro pole dat produktu. Odeberte všechna pole kromě ProductName, CategoryName, SupplierName, UnitPrice a Discontinued. Nebojte se udělat jakékoli estetické přizpůsobení. Rozhodl jsem se pole naformátovat UnitPrice jako hodnotu měny, změnit pořadí polí a přejmenovat několik hodnot polí HeaderText . Také nakonfigurujte GridView tak, aby zahrnoval podporu stránkování a řazení zaškrtnutím políček Povolit stránkování a Povolit řazení v inteligentní značce GridView.

Po přidání ovládacích prvků Panel, Button, GridView a ObjectDataSource a přizpůsobení polí GridView by mělo deklarativní značkování stránky vypadat takto:

<asp:Panel ID="DisplayInterface" runat="server">
    <p>
        <asp:Button ID="ProcessShipment" runat="server" 
            Text="Process Product Shipment" /> 
    </p>
    <asp:GridView ID="ProductsGrid" runat="server" AllowPaging="True" 
        AllowSorting="True" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource">
        <Columns>
            <asp:BoundField DataField="ProductName" HeaderText="Product" 
                SortExpression="ProductName" />
            <asp:BoundField DataField="CategoryName" HeaderText="Category" 
                ReadOnly="True" SortExpression="CategoryName" />
            <asp:BoundField DataField="SupplierName" HeaderText="Supplier" 
                ReadOnly="True" SortExpression="SupplierName" />
            <asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" 
                HeaderText="Price" HtmlEncode="False" 
                SortExpression="UnitPrice">
                <ItemStyle HorizontalAlign="Right" />
            </asp:BoundField>
            <asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued" 
                SortExpression="Discontinued">
                <ItemStyle HorizontalAlign="Center" />
            </asp:CheckBoxField>
        </Columns>
    </asp:GridView>
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
</asp:Panel>

Všimněte si, že tlačítko a objekt GridView se zobrazují v rámci počátečních a uzavíracích <asp:Panel> značek. Vzhledem k tomu, že tyto ovládací prvky jsou v panelu DisplayInterface , můžeme je skrýt jednoduše nastavením vlastnosti Panel na VisibleFalse. Krok 3 se zabývá programovou změnou vlastnosti panelu Visible v reakci na kliknutí na tlačítko zobrazit jedno rozhraní při skrytí druhé.

Chvilku si prohlédněte průběh v prohlížeči. Jak je znázorněno na obrázku 5, měli byste vidět tlačítko pro zpracování zásilky produktu umístěné nad GridView, který zobrazuje seznam produktů po deseti.

GridView obsahuje seznam produktů a nabídek možností řazení a stránkování.

Obrázek 5: Zobrazení seznamů produktů a nabídek řazení a stránkování (kliknutím zobrazíte obrázek v plné velikosti)

Krok 2: Vytvoření rozhraní pro vložení

Po dokončení rozhraní pro zobrazení jsme připraveni vytvořit vložené rozhraní. Pro účely tohoto kurzu vytvoříme vložené rozhraní, které vyzve k zadání jedné hodnoty dodavatele a kategorie a umožní uživateli zadat až pět názvů produktů a jednotkových cenových hodnot. S tímto rozhraním může uživatel přidat jeden do pěti nových produktů, které sdílejí stejnou kategorii a dodavatele, ale mají jedinečné názvy produktů a ceny.

Začněte přetažením panelu z panelu nástrojů do Návrháře a umístěním panelu pod existující DisplayInterface panel. ID Nastavte vlastnost tohoto nově přidaného panelu InsertingInterface a nastavte jeho Visible vlastnost na False. V kroku 3 přidáme kód, který nastaví InsertingInterface vlastnost Visible u True Panelu. Vymažte také hodnoty vlastností panelu Height a Width.

Dále musíme vytvořit rozhraní pro vkládání, které se zobrazilo u obrázku 1. Toto rozhraní lze vytvořit prostřednictvím různých technik HTML, ale my použijeme poměrně jednoduchou tabulku: čtyřsloupce sedmiřádkové tabulky.

Poznámka:

Při zadávání kódu pro elementy HTML <table> dávám přednost použití zobrazení Zdroj. Visual Studio sice obsahuje nástroje pro přidávání <table> prvků prostřednictvím Návrháře, ale zdá se, že Návrhář je příliš ochotný vložit do kódu nezaškrtnutá style nastavení. Po vytvoření <table> značkování se obvykle vrátím do Návrháře, abych přidal Webové ovládací prvky a nastavil jejich vlastnosti. Při vytváření tabulek s předem určenými sloupci a řádky dávám přednost použití statického HTML, nikoli webového ovládacího prvku Table Web, protože k webovým ovládacím prvkům nadřazeným tabulce lze přistupovat pouze pomocí vzoru FindControl("controlID"). Používám však webové ovládací prvky tabulky pro tabulky s dynamickou velikostí (ty, jejichž řádky nebo sloupce jsou založeny na některých kritériích databáze nebo uživatelem), protože ovládací prvek Table Web lze vytvořit programově.

Zadejte následující značky uvnitř tagů <asp:Panel> panelu InsertingInterface:

<table class="DataWebControlStyle" cellspacing="0">
    <tr class="BatchInsertHeaderRow">
        <td class="BatchInsertLabel">Supplier:</td>
        <td></td>
        <td class="BatchInsertLabel">Category:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertAlternatingRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertAlternatingRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertRow">
        <td class="BatchInsertLabel">Product:</td>
        <td></td>
        <td class="BatchInsertLabel">Price:</td>
        <td></td>
    </tr>
    <tr class="BatchInsertFooterRow">
        <td colspan="4">
        </td>
    </tr>
</table>

Tento <table> kód zatím neobsahuje žádné webové ovládací prvky. Tyto ovládací prvky přidáme prozatím. Všimněte si, že každý <tr> prvek obsahuje konkrétní nastavení třídy CSS: BatchInsertHeaderRow pro řádek záhlaví, kam bude umístěn dodavatel a kategorie DropDownLists; BatchInsertFooterRow pro řádek zápatí, kde budou tlačítka Přidat produkty z dodávky a Zrušit umístěna; a hodnoty střídají BatchInsertRow a BatchInsertAlternatingRow pro řádky, které budou obsahovat produktové a cenové TextBoxy. Vytvořil jsem odpovídající třídy CSS v Styles.css souboru, aby rozhraní pro vkládání mělo vzhled podobný ovládacím prvkům GridView a DetailsView, které jsme používali v těchto kurzech. Tyto třídy CSS jsou uvedeny níže.

/*** Styles for ~/BatchData/BatchInsert.aspx tutorial ***/
.BatchInsertLabel
{
    font-weight: bold;
    text-align: right;
}
.BatchInsertHeaderRow td
{
    color: White;
    background-color: #900;
    padding: 11px;
}
.BatchInsertFooterRow td
{
    text-align: center;
    padding-top: 5px;
}
.BatchInsertRow
{
}
.BatchInsertAlternatingRow
{
    background-color: #fcc;
}

Po zadání tohoto kódu se vraťte do návrhového zobrazení. To <table> by se mělo v Návrháři zobrazit jako tabulka se čtyřmi sloupci se sedmi řádky, jak znázorňuje obrázek 6.

Rozhraní pro vkládání se skládá ze čtyřsloupce Seven-Row tabulky.

Obrázek 6: Vložené rozhraní se skládá ze čtyřsloupce Seven-Row tabulky (kliknutím zobrazíte obrázek v plné velikosti).

Teď jsme připraveni přidat webové ovládací prvky do rozhraní pro vložení. Přetáhněte dva rozevírací seznamy ze sady nástrojů do příslušných buněk v tabulce jedna pro dodavatele a jednu pro kategorii.

Nastavte vlastnost DropDownList ID dodavatele na Suppliers a vytvořte vazbu na nový ObjectDataSource s názvem SuppliersDataSource. Nakonfigurujte nový ObjectDataSource tak, aby načetl data z metody třídy SuppliersBLL a nastavte rozevírací seznam karty UPDATE na (None). Kliknutím na tlačítko Dokončit dokončete průvodce.

Konfigurujte ObjectDataSource pro použití třídy SuppliersBLL a její metody GetSuppliers

Obrázek 7: Konfigurace ObjectDataSource pro použití SuppliersBLL metody třídy GetSuppliers (kliknutím zobrazíte obrázek v plné velikosti)

Nechejte rozevírací seznam zobrazit Suppliers datové pole a použít CompanyName datové pole pro jeho hodnoty SupplierID.

Zobrazení datového pole CompanyName a použití ID dodavatele jako hodnoty

Obrázek 8: Zobrazení datového CompanyName pole a použití SupplierID jako hodnoty (kliknutím zobrazíte obrázek s plnou velikostí)

Pojmenujte druhý DropDownList Categories a vytvořte vazbu na nový ObjectDataSource s názvem CategoriesDataSource. CategoriesDataSource Nakonfigurujte ObjectDataSource tak, aby používal metodu CategoriesBLL třídy GetCategories; nastavte rozevírací seznamy na kartách UPDATE a DELETE na (None) a klikněte na Dokončit pro dokončení průvodce. Nakonec nechte DropDownList zobrazovat datové pole CategoryName a použít CategoryID jako hodnotu.

Po přidání těchto dvou rozevíracích seznamů a vázaných na správně nakonfigurované objekty ObjectDataSources by obrazovka měla vypadat podobně jako na obrázku 9.

Řádek záhlaví teď obsahuje rozevírací seznamy dodavatelů a kategorií.

Obrázek 9: Řádek záhlaví teď obsahuje Suppliers a Categories rozevírací seznamy (kliknutím zobrazíte obrázek v plné velikosti).

Teď potřebujeme vytvořit textová pole, abychom shromáždili název a cenu každého nového produktu. Přetáhněte ovládací prvek TextBox z panelu nástrojů do Návrháře pro každý z pěti názvů produktů a cenových řádků. ID Nastavte vlastnosti textových polí na ProductName1, UnitPrice1, ProductName2, UnitPrice2, ProductName3, UnitPrice3, atd.

Přidejte CompareValidator ke každému textovému poli s jednotkovou cenou a nastavte vlastnost ControlToValidate na odpovídající ID. Nastavte také vlastnost Operator na hodnotu GreaterThanEqual, ValueToCompare na hodnotu 0 a Type na hodnotu Currency. Tato nastavení instruují CompareValidator, aby zajistil, že je cena, pokud je zadaná, platná hodnota měny, která je větší nebo rovna nule. Text Nastavte vlastnost *a ErrorMessage na hodnotu Cena musí být větší nebo rovna nule. Také prosím vynechte jakékoli symboly měny.

Poznámka:

Rozhraní pro vkládání neobsahuje žádné ovládací prvky RequiredFieldValidator, i když ProductName pole v Products tabulce databáze nepovoluje NULL hodnoty. Je to proto, že chceme, aby uživatel mohl zadat až pět produktů. Pokud například uživatel zadal název produktu a jednotkovou cenu pro první tři řádky, ponechali jsme poslední dva řádky prázdné, stačí do systému přidat tři nové produkty. Vzhledem k tomu, že ProductName je potřebný, budeme muset programově zkontrolovat, zda je zadána jednotková cena a odpovídající hodnota názvu produktu. Tuto kontrolu vyřešíme v kroku 4.

Při ověřování vstupu uživatele funkce CompareValidator hlásí neplatná data, pokud hodnota obsahuje symbol měny. Přidejte symbol $ před každé textové pole pro zadání jednotkové ceny, které slouží jako vizuální pomůcka poučující uživatele, aby při zadávání ceny vynechal symbol měny.

Nakonec přidejte do panelu InsertingInterface ovládací prvek ValidationSummary, nastavte jeho vlastnost ShowMessageBox na True a jeho vlastnost ShowSummary na False. Pokud uživatel zadá neplatnou hodnotu jednotkové ceny, zobrazí se hvězdička vedle problematických ovládacích prvků TextBox a ValidationSummary zobrazí chybové okno na straně klienta s chybovou zprávou, kterou jsme určili dříve.

V tomto okamžiku by obrazovka měla vypadat podobně jako na obrázku 10.

Rozhraní pro vložení teď obsahuje textová pole pro názvy a ceny produktů.

Obrázek 10: Vložené rozhraní teď obsahuje textová pole pro názvy a ceny produktů (kliknutím zobrazíte obrázek v plné velikosti).

Dále musíme přidat tlačítka Přidat produkty z dodávky a Zrušit do řádku zápatí. Přetáhněte dva ovládací prvky tlačítka z panelu nástrojů do zápatí rozhraní pro vkládání, nastavte vlastnosti tlačítek na ID a AddProducts a vlastnosti na CancelButton a Text pro přidání produktů z dodávky a zrušení. Kromě toho nastavte CancelButton atribut ovládacího prvku CausesValidation na false.

Nakonec musíme přidat ovládací prvek Label Web, který zobrazí stavové zprávy pro obě rozhraní. Když například uživatel úspěšně přidá novou zásilku produktů, chceme se vrátit do rozhraní pro zobrazení a zobrazit potvrzovací zprávu. Pokud však uživatel poskytne cenu nového produktu, ale ponechá název produktu, musíme zobrazit zprávu s upozorněním, protože ProductName pole je povinné. Vzhledem k tomu, že potřebujeme, aby se tato zpráva zobrazovala pro obě rozhraní, umístěte ji v horní části stránky mimo panely.

Přetáhněte ovládací prvek popisek Web z panelu nástrojů do horní části stránky v návrháři. ID Nastavte vlastnost na StatusLabel, vymažte Text vlastnost a nastavte vlastnosti VisibleEnableViewState na False. Jak jsme viděli v předchozích kurzech, nastavení vlastnosti EnableViewState na False nám umožňuje programově měnit hodnoty vlastností štítků a nechat je automaticky vrátit se k výchozím hodnotám při následném zpětném odeslání. To zjednodušuje kód pro zobrazení stavové zprávy v reakci na nějakou akci uživatele, která zmizí v následném zpětném odeslání. Nakonec nastavte vlastnost ovládacího prvku StatusLabel na Warning, což je název třídy CSS definované v CssClass, která zobrazuje text ve velkém, kurzívě, tučném, červeném písmu.

Obrázek 11 znázorňuje Designer Visual Studio po přidání a konfiguraci štítku.

Umístěte ovládací prvek StatusLabel nad ovládací prvky dvou panelů.

Obrázek 11: Umístěte StatusLabel ovládací prvek nad dva ovládací prvky panelu (kliknutím zobrazíte obrázek v plné velikosti)

Krok 3: Přepínání mezi rozhraními pro zobrazení a vkládání

V tuto chvíli jsme dokončili revize pro naše rozhraní pro zobrazení a vkládání, ale stále jsme zůstali se dvěma úkoly:

  • Přepínání mezi rozhraními pro zobrazení a vkládání
  • Přidání produktů do zásilky do databáze

V současné době je rozhraní zobrazení viditelné, ale vložené rozhraní je skryté. Důvodem je, že vlastnost panelu DisplayInterface Panel Visible je nastavena na True (výchozí hodnota), zatímco vlastnost panelu InsertingInterface Panel Visible je nastavena na False. Abychom mohli přepínat mezi dvěma rozhraními, stačí přepnout každou hodnotu vlastnosti ovládacího prvku Visible .

Chceme přejít z rozhraní pro zobrazení do rozhraní pro vložení, když kliknete na tlačítko Zpracovat dodávku produktu. Proto vytvořte obslužnou rutinu události pro tuto událost Button s Click , která obsahuje následující kód:

Protected Sub ProcessShipment_Click(sender As Object, e As EventArgs) _
    Handles ProcessShipment.Click
    DisplayInterface.Visible = False
    InsertingInterface.Visible = True
End Sub

Tento kód jednoduše skryje DisplayInterface panel a zobrazí InsertingInterface panel.

Dále v rozhraní pro vložení vytvořte obslužné rutiny událostí pro ovládací prvky Add Products from Shipment (Přidat produkty z dodávky) a Cancel Button (Tlačítko Zrušit). Když kliknete na některé z těchto tlačítek, musíme se vrátit zpět k rozhraní pro zobrazení. Vytvořte Click obslužné rutiny událostí pro oba tlačítkové ovládací prvky tak, aby volaly ReturnToDisplayInterface, metodu, kterou přidáme za chvíli. Kromě skrytí panelu InsertingInterface a zobrazení panelu DisplayInterfaceReturnToDisplayInterface musí metoda vrátit webové ovládací prvky do stavu před úpravou. To zahrnuje nastavení vlastnosti DropDownLists SelectedIndex na hodnotu 0 a vymazání Text vlastností ovládacích prvků TextBox.

Poznámka:

Než se vrátíme do rozhraní pro zobrazení, zvažte, co se může stát, když jsme ovládací prvky nevrátili do stavu před úpravou. Uživatel může kliknout na tlačítko Zpracovat zásilku produktu, zadat produkty z dodávky a potom kliknout na Přidat produkty z dodávky. Tím přidáte produkty a vrátíte uživatele do rozhraní zobrazení. V tomto okamžiku může uživatel chtít přidat další zásilku. Po kliknutí na tlačítko Zpracovat dodávku produktu se vrátí do rozhraní pro vložení, ale výběry rozbalovacího seznamu a hodnoty textového pole budou stále obsahovat jejich předchozí hodnoty.

Protected Sub AddProducts_Click(sender As Object, e As EventArgs) _
    Handles AddProducts.Click
    ' TODO: Save the products
    ' Revert to the display interface
    ReturnToDisplayInterface()
End Sub
Protected Sub CancelButton_Click(sender As Object, e As EventArgs) _
    Handles CancelButton.Click
    ' Revert to the display interface
    ReturnToDisplayInterface()
End Sub
Const firstControlID As Integer = 1
Const lastControlID As Integer = 5
Private Sub ReturnToDisplayInterface()
    ' Reset the control values in the inserting interface
    Suppliers.SelectedIndex = 0
    Categories.SelectedIndex = 0
    For i As Integer = firstControlID To lastControlID
        CType(InsertingInterface.FindControl _
            ("ProductName" + i.ToString()), TextBox).Text = String.Empty
        CType(InsertingInterface.FindControl _
            ("UnitPrice" + i.ToString()), TextBox).Text = String.Empty
    Next
    DisplayInterface.Visible = True
    InsertingInterface.Visible = False
End Sub

Obě Click obslužné rutiny událostí jednoduše volají metodu ReturnToDisplayInterface, přičemž se ve čtvrtém kroku vrátíme k obslužné rutině události Přidat produkty z zásilky Click a přidáme kód pro uložení produktů. ReturnToDisplayInterface začíná vrácením rozevíracích seznamů Suppliers a Categories k jejich prvním možnostem. Dvě konstanty firstControlID a lastControlID označí hodnoty indexu počátečního a koncového For ovládacího prvku použité při pojmenování názvu produktu a textových polí jednotkové ceny v rozhraní pro vložení a používají se v mezích smyčky, která nastaví Text vlastnosti ovládacích prvků TextBox zpět na prázdný řetězec. Nakonec se vlastnosti panelů Visible resetují, aby bylo rozhraní pro vkládání skryto a rozhraní pro zobrazení viditelné.

Chvíli vyzkoušejte tuto stránku v prohlížeči. Při první návštěvě stránky byste měli vidět rozhraní zobrazení, jak je znázorněno na obrázku 5. Klikněte na tlačítko Zpracovat zásilku produktu. Stránka se obnoví a teď byste měli vidět vkládací rozhraní, jak je znázorněno na obrázku 12. Kliknutím na tlačítko Přidat produkty z dodávky nebo Zrušit se vrátíte do rozhraní pro zobrazení.

Poznámka:

Při prohlížení rozhraní pro vložení si najděte chvíli na otestování CompareValidators v textových polích určených pro jednotkové ceny. Když kliknete na tlačítko Přidat produkty z dodávky s neplatnými hodnotami měny nebo cenami menšími než nula, mělo by se zobrazit výstražné hlášení na straně klienta.

Po kliknutí na tlačítko Zpracovat dodávku produktu se zobrazí rozhraní pro vložení.

Obrázek 12: Po kliknutí na tlačítko Zpracování dodávky produktu se zobrazí rozhraní pro vložení (kliknutím zobrazíte obrázek v plné velikosti).

Krok 4: Přidání produktů

Vše, co zbývá pro tento tutoriál, je uložit produkty do databáze v obslužné rutině události Přidat produkty z tlačítka zásilky Click. Toho lze dosáhnout vytvořením ProductsDataTable a přidáním ProductsRow instance pro každý zadaný název produktu. Po přidání těchto ProductsRow objektů provedeme volání ProductsBLL metody třídy s UpdateWithTransaction předáváním ProductsDataTable. Vzpomeňte si, že UpdateWithTransaction metoda, která byla vytvořena v tutoriálu Zabalování úprav databáze v rámci transakce, předá ProductsDataTable k metodě ProductsTableAdapter objektu UpdateWithTransaction. Odtud se spustí ADO.NET transakce a TableAdapter vydá INSERT příkaz do databáze pro každý přidaný ProductsRow v DataTable. Za předpokladu, že všechny produkty jsou přidány bez chyby, transakce je potvrzena, jinak se vrátí zpět.

Kód obslužné rutiny události Přidat produkty z tlačítka Click zásilky musí také provést kontrolu chyb. Vzhledem k tomu, že v rozhraní pro vkládání nejsou použity žádné RequiredFieldValidators, uživatel může zadat cenu produktu při vynechání jeho názvu. Vzhledem k tomu, že název produktu je povinný, pokud nastane taková podmínka, musíme uživatele upozornit a nepokračovat ve vkládání záznamů. Kompletní kód obslužné rutiny události Click následuje:

Protected Sub AddProducts_Click(sender As Object, e As EventArgs) _
    Handles AddProducts.Click
    ' Make sure that the UnitPrice CompareValidators report valid data...
    If Not Page.IsValid Then Exit Sub
    ' Add new ProductsRows to a ProductsDataTable...
    Dim products As New Northwind.ProductsDataTable()
    For i As Integer = firstControlID To lastControlID
        ' Read in the values for the product name and unit price
        Dim productName As String = CType(InsertingInterface.FindControl _
            ("ProductName" + i.ToString()), TextBox).Text.Trim()
        Dim unitPrice As String = CType(InsertingInterface.FindControl _
            ("UnitPrice" + i.ToString()), TextBox).Text.Trim()
        ' Ensure that if unitPrice has a value, so does productName
        If unitPrice.Length > 0 AndAlso productName.Length = 0 Then
            ' Display a warning and exit this event handler
            StatusLabel.Text = "If you provide a unit price you must also 
                                include the name of the product."
            StatusLabel.Visible = True
            Exit Sub
        End If
        ' Only add the product if a product name value is provided
        If productName.Length > 0 Then
            ' Add a new ProductsRow to the ProductsDataTable
            Dim newProduct As Northwind.ProductsRow = products.NewProductsRow()
            ' Assign the values from the web page
            newProduct.ProductName = productName
            newProduct.SupplierID = Convert.ToInt32(Suppliers.SelectedValue)
            newProduct.CategoryID = Convert.ToInt32(Categories.SelectedValue)
            If unitPrice.Length > 0 Then
                newProduct.UnitPrice = Convert.ToDecimal(unitPrice)
            End If
            ' Add any "default" values
            newProduct.Discontinued = False
            newProduct.UnitsOnOrder = 0
            products.AddProductsRow(newProduct)
        End If
    Next
    ' If we reach here, see if there were any products added
    If products.Count > 0 Then
        ' Add the new products to the database using a transaction
        Dim productsAPI As New ProductsBLL()
        productsAPI.UpdateWithTransaction(products)
        ' Rebind the data to the grid so that the products just added are displayed
        ProductsGrid.DataBind()
        ' Display a confirmation (don't use the Warning CSS class, though)
        StatusLabel.CssClass = String.Empty
        StatusLabel.Text = String.Format( _
            "{0} products from supplier {1} have been " & _
            "added and filed under category {2}.", _
            products.Count, Suppliers.SelectedItem.Text, Categories.SelectedItem.Text)
        StatusLabel.Visible = True
        ' Revert to the display interface
        ReturnToDisplayInterface()
    Else
        ' No products supplied!
        StatusLabel.Text = 
            "No products were added. Please enter the " & _
            "product names and unit prices in the textboxes."
        StatusLabel.Visible = True
    End If
End Sub

Obslužná rutina události začíná zajištěním, že Page.IsValid vlastnost vrací hodnotu True. Pokud se vrátí False, znamená to, že jeden nebo více porovnávačů hlásí neplatná data. V takovém případě se nechceme pokoušet vložit zadané produkty, protože bychom skončili s výjimkou při pokusu o přiřazení hodnoty jednotkové ceny zadané uživatelem ke vlastnosti ProductsRow.

Dále se vytvoří nová ProductsDataTable instance (products). Smyčka For se používá k iteraci přes textová pole názvu produktu a jednotkové ceny, přičemž vlastnosti Text se načtou do místních proměnných productName a unitPrice. Pokud uživatel zadal hodnotu pro jednotkovou cenu, ale ne pro odpovídající název produktu, zobrazí se zpráva Pokud zadáte jednotkovou cenu, StatusLabel musíte zahrnout také název produktu a obslužná rutina události se ukončí.

Pokud byl zadán název produktu, vytvoří se nová ProductsRow instance pomocí ProductsDataTable metody s NewProductsRow . Tato nová instanční vlastnost ProductsRow je vlastnost ProductName nastavena na TextBox aktuálního názvu produktu, zatímco vlastnosti SupplierID a CategoryID jsou přiřazeny vlastnostem SelectedValue rozbalovacích seznamů v hlavičce rozhraní pro vkládání. Pokud uživatel zadal hodnotu pro cenu produktu, je přiřazena k vlastnosti instance ProductsRowUnitPrice; jinak zůstane vlastnost nepřiřazená, což bude mít za následek hodnotu NULL pro UnitPrice v databázi. Discontinued UnitsOnOrder Nakonec jsou vlastnosti přiřazeny pevně zakódovaným hodnotám False a 0.

Po přiřazení vlastností k ProductsRow instanci je přidán do objektu ProductsDataTable.

Po dokončení smyčky For zkontrolujeme, jestli byly přidány nějaké produkty. Uživatel může po všem kliknout na položku Přidat produkty z dodávky před zadáním jakýchkoli názvů produktů nebo cen. Pokud je v ProductsDataTable alespoň jeden produkt, je volána metoda třídy ProductsBLL s UpdateWithTransaction. V dalším kroku se data převedou do objektu ProductsGrid GridView, aby se nově přidané produkty zobrazily v rozhraní zobrazení. Aktualizuje se StatusLabel tak, aby zobrazila potvrzovací zprávu, a ReturnToDisplayInterface se vyvolá, čímž se skryje rozhraní pro vkládání a zobrazí se rozhraní pro zobrazení.

Pokud nebyly zadány žádné produkty, rozhraní pro vkládání zůstane zobrazeno, ale zpráva Nebyly přidány žádné produkty. Do textových polí zadejte názvy produktů a ceny jednotek.

Obrázek 13, 14 a 15 znázorňují rozhraní vložení a zobrazení v akci. Na obrázku 13 uživatel zadal jednotkovou cenu bez odpovídajícího názvu produktu. Obrázek 14 ukazuje rozhraní pro zobrazení po úspěšném přidání tří nových produktů, zatímco obrázek 15 ukazuje dva nově přidané produkty v GridView (třetí je na předchozí stránce).

Při zadávání jednotkové ceny se vyžaduje název produktu.

Obrázek 13: Při zadávání jednotkové ceny je požadován název produktu (kliknutím zobrazíte obrázek v plné velikosti).

Byly přidány tři nové zeleniny pro dodavatele Mayumi

Obrázek 14: Byly přidány tři novéggy pro dodavatele Mayumi s (kliknutím zobrazíte obrázek s plnou velikostí)

Nové produkty najdete na poslední stránce objektu GridView.

Obrázek 15: Nové produkty najdete na poslední stránce objektu GridView (kliknutím zobrazíte obrázek v plné velikosti).

Poznámka:

Logika dávkového vkládání použitá v tomto kurzu obklopuje vložení uvnitř rozsahu transakce. Chcete-li to ověřit, účelně zavést chybu na úrovni databáze. Například místo přiřazení vlastnosti ProductsRow nové CategoryID instance k vybrané hodnotě v rozevíracím seznamu Categories, přiřaďte ji k hodnotě, jakou je i * 5. Tady i je indexer smyčky a má hodnoty v rozsahu od 1 do 5. Proto při hromadném vložení dvou nebo více produktů bude mít první produkt platnou CategoryID hodnotu (5), ale následné produkty budou mít odlišné CategoryID hodnoty, které neodpovídají CategoryID hodnotám v Categories tabulce. Výsledkem je, že zatímco první INSERT bude úspěšný, následné selžou kvůli porušení omezení cizího klíče. Vzhledem k tomu, že dávkové vložení je atomické, první INSERT se vrátí zpět a vrátí databázi do jejího stavu před zahájením procesu dávkového vložení.

Shrnutí

Během tohoto a předchozích dvou kurzů jsme vytvořili rozhraní, která umožňují aktualizovat, odstraňovat a vkládat dávky dat, přičemž všechna tato rozhraní používala podporu transakcí, kterou jsme přidali do vrstvy přístupu k datům v kurzu Zapouzdření úprav databáze v rámci transakce. V některých scénářích tato uživatelská rozhraní dávkového zpracování výrazně zlepšují efektivitu koncových uživatelů snížením počtu kliknutí, postbacků a přepínačů kontextu mezi klávesami a myší a zároveň zachováním integrity podkladových dat.

V tomto kurzu se podíváme na práci s dávkovými daty. Další sada kurzů zkoumá celou řadu pokročilých scénářů vrstvy přístupu k datům, včetně použití uložených procedur v metodách TableAdapter, konfigurace nastavení na úrovni připojení a příkazů v DAL, šifrování připojovacích řetězců a další!

Šťastné programování!

O autorovi

Scott Mitchell, autor sedmi knih ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, trenér a spisovatel. Jeho nejnovější kniha je Sams Naučte se sami ASP.NET 2.0 za 24 hodin. Může být dosažitelný na mitchell@4GuysFromRolla.comadrese .

Zvláštní díky

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Vedoucí hodnotitelé tohoto tutoriálu byli Hilton Giesenow a Søren Jacob Lauritsen. Chcete si projít nadcházející články MSDN? Pokud ano, napište mi zprávu na mitchell@4GuysFromRolla.com.