Sdílet prostřednictvím


Dávkové vkládání (C#)

Scott Mitchell

Stáhnout PDF

Zjistěte, jak v jedné operaci vložit více databázových záznamů. 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 zabalíme několik operací vložení v rámci transakce, abychom zajistili, že všechna vložení budou úspěšná nebo vrácená zpět.

Úvod

V kurzu Dávkové aktualizace jsme se podívali na přizpůsobení ovládacího prvku GridView tak, aby bylo možné upravit více záznamů. Uživatel, který stránku navštíví, může provést řadu změn a potom jedním kliknutím na tlačítko provést dávkovou aktualizaci. V situacích, kdy uživatelé často aktualizují mnoho záznamů najednou, může takové rozhraní ušetřit nespočet kliknutí a kontextových přepínačů mezi klávesami a myší ve srovnání s výchozími funkcemi pro úpravy jednotlivých řádků, které byly poprvé prozkoumány v kurzu Přehled vkládání, aktualizací a odstraňování dat .

Tento koncept lze použít také při přidávání záznamů. Představte si, že tady v Northwind Traders běžně přijímáme zásilky od dodavatelů, které obsahují řadu produktů pro určitou kategorii. Například můžeme obdržet zásilku šesti různých produktů na čaj a kávu od společnosti Tokyo Traders. Pokud uživatel zadá šest produktů po jednom prostřednictvím ovládacího prvku DetailsView, bude muset zvolit mnoho stejných hodnot znovu a znovu: bude muset zvolit 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 je nejen časově náročné, ale také náchylné k chybám.

S trochou práce můžeme vytvořit rozhraní pro vkládání dávek, které uživateli umožní vybrat dodavatele a kategorii jednou, zadat řadu názvů produktů a jednotkových cen a potom 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ým polím přiřazeny hodnoty zadané v textových polích, zatímco hodnoty CategoryID a SupplierID 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.

Rozhraní batch inserting interface

Obrázek 1: Rozhraní Batch Inserting Interface (kliknutím zobrazíte obrázek v plné velikosti)

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 kurzech zabalíme vložení do rozsahu transakce, abychom zajistili nedělitelnost. Pusťme se do toho!

Krok 1: Vytvoření rozhraní zobrazení

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

Při vytváření stránky, která má dvě rozhraní, z nichž pouze jedno je viditelné najednou, je každé rozhraní obvykle umístěno v rámci webového ovládacího prvku Panel, který slouží jako kontejner pro jiné ovládací prvky. Proto bude naše stránka mít dva ovládací prvky Panel jeden pro každé rozhraní.

Začněte tím, že BatchInsert.aspx otevřete stránku ve BatchData složce a přetáhnete panel z panelu nástrojů na Designer (viz obrázek 2). Nastavte vlastnost Panel s ID na DisplayInterface. Při přidávání panelu do Designer jsou vlastnosti Height a Width nastaveny na 50px a 125px v uvedeném pořadí. Vymažte tyto hodnoty vlastností ze okno Vlastnosti.

Přetažení panelu z panelu nástrojů na Designer

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

Dále přetáhněte ovládací prvek Button a GridView do panelu. Nastavte vlastnost Tlačítka ID na ProcessShipment a její Text vlastnost na Process Product Shipment (Zpracovat zásilku produktu). Nastavte vlastnost GridView na IDProductsGrid a z její inteligentní značky vytvořte vazbu na nový objekt ObjectDataSource s názvem ProductsDataSource. Nakonfigurujte ObjectDataSource tak, aby načítá data z ProductsBLL metody třídy s GetProducts . Vzhledem k tomu, že se toto zobrazení GridView používá jenom k zobrazení dat, nastavte rozevírací seznamy na kartách UPDATE, INSERT a DELETE na (Žádné). Kliknutím na Dokončit dokončete průvodce Konfigurací zdroje dat.

Zobrazení dat vrácených metodou 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 AKTUALIZOVAT, VLOŽIT a ODSTRANIT na (Žádné).

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

Po dokončení průvodce ObjectDataSource přidá Visual Studio boundFields a CheckBoxField pro datová pole produktu. Odeberte všechna pole kromě ProductNamepolí , CategoryNameSupplierName, , UnitPricea Discontinued . Nebojte se udělat jakékoli estetické přizpůsobení. Rozhodl(a) jsem se pole naformátovat UnitPrice jako hodnotu měny, změnit pořadí polí a přejmenovat několik hodnot polí HeaderText . Nakonfigurujte také 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 deklarativní značky stránky měly vypadat nějak 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 značky Button a GridView se zobrazí v rámci počáteční a uzavírací <asp:Panel> značky. Vzhledem k tomu, že jsou tyto ovládací prvky v rámci panelu DisplayInterface , můžeme je skrýt jednoduchým nastavením vlastnosti Panel na Visiblefalse. Krok 3 se zabývá programovou změnou vlastnosti Panel s Visible v reakci na kliknutí na tlačítko pro zobrazení jednoho rozhraní a skrytí druhého.

Podívejte se na průběh v prohlížeči. Jak je znázorněno na obrázku 5, mělo by se nad objektem GridView zobrazit tlačítko Zpracovat zásilku produktu, které obsahuje seznam produktů najednou.

GridView Seznamy možnosti řazení a stránkování produktů a nabídek

Obrázek 5: GridView Seznamy možnosti řazení a stránkování produktů a nabídek (kliknutím zobrazíte obrázek v plné velikosti)

Krok 2: Vytvoření rozhraní pro vkládání

Po dokončení rozhraní pro zobrazení jsme připraveni vytvořit rozhraní pro vkládání. Pro účely tohoto kurzu vytvoříme rozhraní pro vkládání, 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 cen. Pomocí tohoto rozhraní může uživatel přidat jeden až pět nových produktů, které mají 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ů na Designer a jeho umístěním pod existující DisplayInterface panel. ID Nastavte vlastnost tohoto nově přidaného panelu na InsertingInterface a nastavte jeho Visible vlastnost na false. V kroku 3 přidáme kód, který nastaví InsertingInterface vlastnost Panel Visible na true . Vymažte také hodnoty panelů Height a Width vlastností.

Dále musíme vytvořit rozhraní pro vkládání, které bylo znázorněno na obrázku 1. Toto rozhraní lze vytvořit pomocí různých technik HTML, ale použijeme poměrně přímočarou: čtyřsloupovou sedmiřádkovou tabulku.

Poznámka

Při zadávání značek pro elementy HTML <table> dávám přednost zobrazení Zdroj. I když sada Visual Studio obsahuje nástroje pro přidávání <table> prvků prostřednictvím Designer, zdá se, že Designer je příliš ochotná style vložit do značek nastavení bez přiřazení. Po vytvoření <table> kódu se obvykle vrátím do Designer přidat webové ovládací prvky a nastavit 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 než webového ovládacího prvku Tabulka , protože všechny webové ovládací prvky umístěné v rámci webového FindControl("controlID") ovládacího prvku Tabulka jsou přístupné pouze pomocí vzoru . 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 databázových nebo uživatelem zadaných kritériích), protože webový ovládací prvek Tabulka lze vytvořit programově.

Do značek InsertingInterface panelu <asp:Panel> zadejte následující kód:

<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, přidáme je na chvíli. Všimněte si, že každý <tr> prvek obsahuje konkrétní nastavení třídy CSS: BatchInsertHeaderRow pro řádek záhlaví, kam se přesune dodavatel a kategorie DropDownLists; BatchInsertFooterRow pro řádek zápatí, kde budou tlačítka Přidat produkty z dodávky a Zrušit; a střídavé BatchInsertRow hodnoty a BatchInsertAlternatingRow pro řádky, které budou obsahovat ovládací prvky TextBox produktu a jednotkové ceny. Vytvořil jsem odpovídající třídy CSS v Styles.css souboru, aby se vkládání rozhraní vzhled podobný ovládacím prvkům GridView a DetailsView, které jsme použili v rámci těchto kurzů. Tyto třídy šablon stylů CSS jsou zobrazeny 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 zobrazit jako sedmiřádková tabulka se čtyřmi sloupci v Designer, jak je znázorněno na obrázku 6.

Rozhraní pro vkládání se skládá z tabulky se čtyřmi sloupci Seven-Row.

Obrázek 6: Rozhraní pro vkládání se skládá z tabulky se čtyřmi sloupci Seven-Row (kliknutím zobrazíte obrázek v plné velikosti).

Teď jsme připraveni přidat webové ovládací prvky do rozhraní pro vkládání. Přetáhněte dva rozevírací seznamy z panelu nástrojů do příslušných buněk v tabulce, jednu pro dodavatele a jednu pro kategorii.

Nastavte vlastnost dropDownList dodavatele ID na Suppliers a vytvořte vazbu s novým objektem ObjectDataSource s názvem SuppliersDataSource. Nakonfigurujte nový objekt ObjectDataSource tak, aby načítal data z SuppliersBLL metody třídy s GetSuppliers , a nastavte rozevírací seznam UPDATE tab s na hodnotu (None). Dokončete průvodce kliknutím na Dokončit.

Nakonfigurujte ObjectDataSource tak, aby používal metodu SuppliersBLL Class s GetSuppliers.

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

Nechte rozevírací seznam Suppliers zobrazit CompanyName datové pole a použít SupplierID datové pole jako jeho ListItem hodnoty s.

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

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

Pojmenujte druhý dropDownList Categories a vytvořte vazbu na nový objekt ObjectDataSource s názvem CategoriesDataSource. CategoriesDataSource Nakonfigurujte ObjectDataSource tak, aby používal metodu CategoriesBLL třídy sGetCategories. Nastavte rozevírací seznamy na kartách UPDATE a DELETE na (None) a kliknutím na Dokončit dokončete průvodce. Nakonec nechte DropDownList zobrazit CategoryName datové pole a použít CategoryID jako hodnotu hodnotu.

Po přidání těchto dvou rozevíracích seznamů a jejich vazbě na správně nakonfigurované ObjectDataSources by vaše obrazovka měla vypadat podobně jako na obrázku 9.

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

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

Teď musíme 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ů na Designer pro každý z pěti řádků názvu produktu a ceny. ID Nastavte vlastnosti textových polí na ProductName1, UnitPrice1, ProductName2, UnitPrice2ProductName3, , UnitPrice3atd.

Přidejte CompareValidator za každé pole textových polí jednotkové ceny a nastavte ControlToValidate vlastnost na odpovídající IDhodnotu . Vlastnost také nastavte Operator na GreaterThanEqual, ValueToCompare na 0 a Type na Currency. Tato nastavení instruují CompareValidator, aby zajistil, že cena, pokud je zadána, je platná hodnota měny, která je větší než nebo rovna nule. Text Nastavte vlastnost na *a ErrorMessage na Hodnotu Cena musí být větší nebo rovna nule. Vyněnejte také 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 zadal až pět produktů. Pokud například uživatel zadá název produktu a jednotkovou cenu pro první tři řádky a ponechá poslední dva řádky prázdné, přidáme do systému jenom tři nové produkty. Vzhledem k tomu ProductName , že je to povinné, budeme muset programově zkontrolovat, abychom zajistili, že pokud je zadána jednotková cena, je zadána odpovídající hodnota názvu produktu. Touto kontrolou se budeme zabývat 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 $ před každé z jednotkových cen textových polí, která budou sloužit jako vizuální upozornění, které uživateli dává pokyn, aby při zadávání ceny vynechal symbol měny.

Nakonec přidejte ovládací prvek ValidationSummary v rámci panelu InsertingInterface a jeho vlastnost na trueShowSummaryfalse.ShowMessageBox Pokud uživatel s těmito nastaveními zadá neplatnou jednotkovou cenu, zobrazí se vedle urážených ovládacích prvků TextBox hvězdička a ValidationSummary zobrazí okno se zprávou na straně klienta, které zobrazuje chybovou zprávu, kterou jsme zadali dříve.

V tomto okamžiku by vaše obrazovka měla vypadat podobně jako obrázek 10.

Vložené rozhraní 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 Button z panelu nástrojů do zápatí rozhraní pro vkládání a nastavujte vlastnosti Tlačítka ID na AddProducts a CancelButton na Text Přidat produkty z dodávky a Zrušit. Kromě toho nastavte CancelButton vlastnost ovládacího prvku s CausesValidation na falsehodnotu .

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

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

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

Umístěte ovládací prvek StatusLabel nad ovládací prvky Dva panely.

Obrázek 11: Umístěte StatusLabel ovládací prvek nad ovládací prvky Dva panely (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 tomto okamžiku jsme dokončili revize pro naše rozhraní pro zobrazení a vkládání, ale stále nám zbývá dvě úlohy:

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

V současné době je rozhraní zobrazení viditelné, ale rozhraní pro vkládání je skryté. Důvodem je to, že DisplayInterface vlastnost Panel s Visible je nastavená na true hodnotu (výchozí hodnota), zatímco InsertingInterface vlastnost Panel s Visible je nastavená na falsehodnotu . Pokud chcete přepínat mezi těmito dvěma rozhraními, stačí přepnout hodnotu vlastnosti každého ovládacího prvku Visible .

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

protected void ProcessShipment_Click(object sender, EventArgs e)
{
    DisplayInterface.Visible = false;
    InsertingInterface.Visible = true;
}

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

Dále vytvořte obslužné rutiny událostí pro ovládací prvky Přidat produkty z dodávky a Tlačítko zrušit v rozhraní pro vkládání. Po kliknutí na některé z těchto tlačítek se musíme vrátit zpět k rozhraní zobrazení. Vytvořte Click obslužné rutiny událostí pro oba ovládací prvky Button tak, aby volaly ReturnToDisplayInterfacemetodu, kterou na chvíli přidáme. Kromě skrytí panelu InsertingInterface a zobrazení panelu DisplayInterfaceReturnToDisplayInterface musí metoda vrátit webové ovládací prvky do jejich stavu před úpravami. To zahrnuje nastavení vlastnosti DropDownLists SelectedIndex na hodnotu 0 a vymazání Text vlastností TextBox ovládacích prvků.

Poznámka

Zvažte, co se může stát, kdybychom před návratem do rozhraní zobrazení nevrátili ovládací prvky do stavu před úpravami. Uživatel může kliknout na tlačítko Zpracovat dodávku produktu, zadat produkty z dodávky a potom kliknout na Přidat produkty z dodávky. To by přidalo produkty a vrátilo 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 DropDownList a TextBox hodnoty budou stále naplněny jejich předchozími hodnotami.

protected void AddProducts_Click(object sender, EventArgs e)
{
    // TODO: Save the products
    // Revert to the display interface
    ReturnToDisplayInterface();
}
protected void CancelButton_Click(object sender, EventArgs e)
{
    // Revert to the display interface
    ReturnToDisplayInterface();
}
const int firstControlID = 1;
const int lastControlID = 5;
private void ReturnToDisplayInterface()
{
    // Reset the control values in the inserting interface
    Suppliers.SelectedIndex = 0;
    Categories.SelectedIndex = 0;
    for (int i = firstControlID; i <= lastControlID; i++)
    {
        ((TextBox)InsertingInterface.FindControl("ProductName" + i.ToString())).Text =
            string.Empty;
        ((TextBox)InsertingInterface.FindControl("UnitPrice" + i.ToString())).Text = 
            string.Empty;
    }
    DisplayInterface.Visible = true;
    InsertingInterface.Visible = false;
}

Obě Click obslužné rutiny událostí jednoduše volají metodu ReturnToDisplayInterface , i když se vrátíme k obslužné rutině události Přidat produkty z dodávky Click v kroku 4 a přidáme kód pro uložení produktů. ReturnToDisplayInterface Začne vrácením Suppliers prvních možností a Categories DropDownLists. Dvě konstanty firstControlID a lastControlID označí hodnoty indexu počátečního a koncového ovládacího prvku použité při pojmenování názvu produktu a jednotkové ceny TextBoxes v rozhraní pro vložení a jsou použity v mezích for smyčky, která nastaví Text vlastnosti ovládacích prvků TextBox zpět na prázdný řetězec. Nakonec se vlastnosti Panely Visible resetují, takže rozhraní pro vkládání je skryté a zobrazí se rozhraní pro zobrazení.

Chvíli si tuto stránku otestujte 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 dodávku produktu. Stránka se vrátí zpět a teď byste měli vidět rozhraní pro vkládání, jak je znázorněno na obrázku 12. Kliknutím na tlačítka Přidat produkty ze zásilky nebo Zrušit se vrátíte do rozhraní zobrazení.

Poznámka

Při prohlížení rozhraní pro vkládání chvíli otestujte CompareValidators v textových polích s jednotkovou cenou. Po kliknutí na tlačítko Přidat produkty z dodávky s neplatnými hodnotami měny nebo cenami s hodnotou menší než nula by se měla zobrazit zpráva na straně klienta.

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

Obrázek 12: Po kliknutí na tlačítko Zpracovat dodávku 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 kurz, je uložit produkty do databáze v obslužné rutině události Přidat produkty z tlačítka Click dodávky. Toho lze dosáhnout vytvořením ProductsDataTable a přidáním ProductsRow instance pro každý z dodaných názvů produktů. Po přidání těchto ProductsRow s provedeme volání ProductsBLL metody třídy s UpdateWithTransaction , která předává metodu ProductsDataTable. Vzpomeňte UpdateWithTransaction si, že metoda, která byla vytvořena zpět v kurzu Obtékání změn databáze v rámci transakce , předává metodu ProductsDataTableProductsTableAdapter s UpdateWithTransaction . Odtud se spustí transakce ADO.NET a objekt TableAdapter vydá do databáze příkaz pro každou přidanou INSERTProductsRow do tabulky DataTable. Za předpokladu, že jsou všechny produkty přidány bez chyby, transakce je potvrzena, jinak je vrácena zpět.

Kód pro obslužnou rutinu události Add Products from Shipment Button s Click 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 a vynechat jeho název. Vzhledem k tomu, že se vyžaduje název produktu, musíme v případě, že se taková podmínka rozvine, upozornit uživatele a nepokračovat v vložení. Úplný Click kód obslužné rutiny události následuje:

protected void AddProducts_Click(object sender, EventArgs e)
{
    // Make sure that the UnitPrice CompareValidators report valid data...
    if (!Page.IsValid)
        return;
    // Add new ProductsRows to a ProductsDataTable...
    Northwind.ProductsDataTable products = new Northwind.ProductsDataTable();
    for (int i = firstControlID; i <= lastControlID; i++)
    {
        // Read in the values for the product name and unit price
        string productName = ((TextBox)InsertingInterface.FindControl
            ("ProductName" + i.ToString())).Text.Trim();
        string unitPrice = ((TextBox)InsertingInterface.FindControl
            ("UnitPrice" + i.ToString())).Text.Trim();
        // Ensure that if unitPrice has a value, so does productName
        if (unitPrice.Length > 0 && productName.Length == 0)
        {
            // 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;
            return;
        }
        // Only add the product if a product name value is provided
        if (productName.Length > 0)
        {
            // Add a new ProductsRow to the ProductsDataTable
            Northwind.ProductsRow newProduct = 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)
                newProduct.UnitPrice = Convert.ToDecimal(unitPrice);
            // Add any "default" values
            newProduct.Discontinued = false;
            newProduct.UnitsOnOrder = 0;
            products.AddProductsRow(newProduct);
        }
    }
    // If we reach here, see if there were any products added
    if (products.Count > 0)
    {
        // Add the new products to the database using a transaction
        ProductsBLL productsAPI = 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;
    }
}

Obslužná rutina události začíná tím, že zajistí, aby Page.IsValid vlastnost vrátila hodnotu true. Pokud vrátí falsehodnotu , znamená to, že jeden nebo více rutin CompareValidators hlásí neplatná data. V takovém případě se nechceme pokusit vložit zadané produkty nebo při pokusu o přiřazení hodnoty jednotkové ceny zadané uživatelem k vlastnosti s UnitPrice dojde k ProductsRow výjimce.

Dále se vytvoří nová ProductsDataTable instance (products). Smyčka for se používá k iteraci v textových polích s názvem produktu a jednotkovou cenou a Text vlastnosti 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, StatusLabel zobrazí se zpráva Pokud zadáte jednotkovou cenu, musíte také zahrnout 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á ProductsRow vlastnost instance s ProductName je nastavena na aktuální název produktu TextBox, zatímco SupplierID vlastnosti a CategoryID jsou přiřazeny SelectedValue vlastnosti DropDownLists v vložení rozhraní s hlavičky. Pokud uživatel zadal hodnotu pro cenu produktu, je přiřazena k ProductsRow vlastnosti instance s UnitPrice ; v opačném případě se vlastnost ponechá nepřiřazená, což způsobí NULL hodnotu pro UnitPrice v databázi. Discontinued Nakonec jsou vlastnosti a UnitsOnOrder přiřazeny pevně zakódovaným hodnotám false a 0 v uvedeném pořadí.

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

Po dokončení smyčky for zkontrolujeme, jestli byly přidány nějaké produkty. Uživatel může koneckonců kliknout na Přidat produkty ze zásilky před zadáním názvů produktů nebo cen. Pokud existuje alespoň jeden produkt v ProductsDataTable, ProductsBLL je volána metoda třídy s UpdateWithTransaction . Dále se data vrátí do objektu ProductsGrid GridView, aby se nově přidané produkty zobrazily v rozhraní pro zobrazení. Aktualizuje StatusLabel se tak, aby se zobrazila potvrzovací zpráva, a ReturnToDisplayInterface vyvolá se. Skryje se rozhraní pro vložení a zobrazí se rozhraní pro zobrazení.

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

Obrázek 13, 14 a 15 znázorňuje rozhraní pro vkládání a zobrazení v akci. Na obrázku 13 uživatel zadal jednotkovou cenu bez odpovídajícího názvu produktu. Obrázek 14 znázorňuje rozhraní zobrazení po úspěšném přidání tří nových produktů, zatímco obrázek 15 znázorňuje 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 se vyžaduje název produktu (kliknutím zobrazíte obrázek v plné velikosti)

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

Obrázek 14: Byly přidány tři nové zelenina pro dodavatele Mayumi s (kliknutím zobrazíte obrázek v plné velikosti)

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

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

Poznámka

Logika dávkového vkládání použitá v tomto kurzu zabalí vložení do rozsahu transakce. Chcete-li to ověřit, záměrně zavete chybu na úrovni databáze. Například místo přiřazení vlastnosti nové ProductsRow instance s CategoryID vybrané hodnotě v rozevíracím Categories seznamu ji přiřaďte k hodnotě, jako je i * 5. Tady i je indexer smyčky a obsahuje hodnoty v rozsahu od 1 do 5. Proto při přidávání dvou nebo více produktů v dávce vložte první produkt bude mít platnou CategoryID hodnotu (5), ale následující produkty budou mít CategoryID hodnoty, které neodpovídají hodnotám CategoryID v Categories tabulce. Čistý efekt spočívá v tom, že zatímco první INSERT bude úspěšný, další selžou s porušením 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 stavu před zahájením procesu dávkového vložení.

Souhrn

V tomto a předchozích dvou kurzech jsme vytvořili rozhraní, která umožňují aktualizovat, odstraňovat a vkládat dávky dat, přičemž všechny využívají podporu transakcí, kterou jsme přidali do vrstvy přístupu k datům v kurzu Obtékání úprav databáze v rámci transakce . V některých scénářích takové dávkové zpracování uživatelských rozhraní výrazně vylepšuje efektivitu koncových uživatelů tím, že snižuje počet kliknutí, zpětného volání a kontextových přepínačů pomocí klávesnice na myš a současně zachovává integritu podkladových dat.

Tento kurz doplňuje náš pohled na práci s daty v dávkách. Další sada kurzů prozkoumá 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 s, konfigurace nastavení na úrovni připojení a příkazů v dal, šifrování připojovacích řetězců a dalších!

Šťastné programování!

O autorovi

Scott Mitchell, autor sedmi knih o ASP/ASP.NET a zakladatel 4GuysFromRolla.com, pracuje s webovými technologiemi Microsoftu od roku 1998. Scott pracuje jako nezávislý konzultant, školitel a spisovatel. Jeho nejnovější kniha je Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Můžete ho najít na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na http://ScottOnWriting.NETadrese .

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty tohoto kurzu byly Hilton Giesenow a S ren Jacob Lauritsen. Chcete si projít moje nadcházející články na WEBU MSDN? Pokud ano, dejte mi čáru na mitchell@4GuysFromRolla.comadresu .