Sdílet prostřednictvím


Dávkové aktualizace (C#)

Scott Mitchell

Stáhnout PDF

Zjistěte, jak aktualizovat více databázových záznamů v rámci jedné operace. Ve vrstvě uživatelského rozhraní vytvoříme Objekt GridView, ve kterém lze každý řádek upravovat. Ve vrstvě přístupu k datům zabalíme několik operací aktualizace v rámci transakce, abychom zajistili, že všechny aktualizace proběhnou úspěšně nebo se vrátí zpět.

Úvod

V předchozím kurzu jsme viděli, jak rozšířit vrstvu přístupu k datům, aby se přidala podpora databázových transakcí. Databázové transakce zaručují, že řada příkazů pro úpravu dat bude považována za jednu atomickou operaci, která zajistí, že všechny úpravy selžou nebo všechny budou úspěšné. S touto nízkoúrovňovou funkcí DAL mimo cestu jsme připraveni obrátit pozornost na vytváření rozhraní pro dávkové úpravy dat.

V tomto kurzu vytvoříme objekt GridView, ve kterém bude možné upravovat každý řádek (viz obrázek 1). Vzhledem k tomu, že se každý řádek vykresluje ve svém rozhraní pro úpravy, není potřeba používat sloupec tlačítek Upravit, Aktualizovat a Zrušit. Místo toho jsou na stránce dvě tlačítka Aktualizovat produkty, která po kliknutí zobrazí výčet řádků GridView a aktualizují databázi.

Každý řádek v zobrazení GridView je upravitelný.

Obrázek 1: Každý řádek v zobrazení GridView je upravitelný (kliknutím zobrazíte obrázek v plné velikosti)

Pusťme se do toho!

Poznámka

V kurzu Provádění Aktualizace batch jsme vytvořili rozhraní pro dávkové úpravy pomocí ovládacího prvku DataList. Tento kurz se liší od předchozího v tom, že se používá GridView a dávková aktualizace se provádí v rámci rozsahu transakce. Po dokončení tohoto kurzu vám doporučujeme vrátit se k předchozímu kurzu a aktualizovat ho tak, aby používal funkce související s databázovými transakcemi přidané v předchozím kurzu.

Prozkoumání kroků pro úpravu všech řádků GridView

Jak je popsáno v kurzu Přehled vložení, aktualizace a odstranění dat , GridView nabízí integrovanou podporu pro úpravy podkladových dat po jednotlivých řádcích. Interně GridView zaznamenává, který řádek je upravitelný prostřednictvím jeho EditIndex vlastnosti. Vzhledem k tomu, že objekt GridView je svázán se svým zdrojem dat, kontroluje každý řádek a zjišťuje, jestli se index řádku rovná hodnotě EditIndex. Pokud ano, tato pole řádků se vykreslují pomocí jejich rozhraní pro úpravy. Pro BoundFields je rozhraní pro úpravy TextBox, jehož Text vlastnost je přiřazena hodnota datového pole určená vlastnost BoundField s DataField . Pro TemplateFields se EditItemTemplate místo ItemTemplatepoužije .

Vzpomeňte si, že pracovní postup úprav se spustí, když uživatel klikne na tlačítko Upravit na řádku. To způsobí postback, nastaví GridView s EditIndex vlastnost na index řádku s kliknutí a znovu binuje data k mřížce. Při kliknutí na tlačítko Zrušit řádku se při zpětném odeslání EditIndex nastaví hodnota na hodnotu -1 před opětovnou vazbou dat do mřížky. Vzhledem k tomu, GridView s řádky začít indexování na nule, nastavení EditIndex na -1 má vliv na zobrazení GridView v režimu jen pro čtení.

Vlastnost EditIndex funguje dobře pro úpravy jednotlivých řádků, ale není určená pro dávkové úpravy. Aby bylo možné upravovat celý Objekt GridView, musíme každý řádek vykreslit pomocí jeho rozhraní pro úpravy. Nejjednodušší způsob, jak toho dosáhnout, je vytvořit, kde se každé upravitelné pole implementuje jako TemplateField s jeho rozhraním pro úpravy definovaným ItemTemplatev .

V následujících několika krocích vytvoříme zcela upravitelný objekt GridView. V kroku 1 začneme vytvořením objektu GridView a jeho objektu ObjectDataSource a jeho převedením BoundFields a CheckBoxField na TemplateFields. V krocích 2 a 3 přesuneme rozhraní pro úpravy z polí TemplateFields EditItemTemplate do jejich ItemTemplate .

Krok 1: Zobrazení informací o produktu

Než se začneme zabývat vytvořením objektu GridView, ve kterém se dají upravovat řádky, začněme jednoduchým zobrazením informací o produktu. BatchUpdate.aspx Otevřete stránku ve BatchData složce a přetáhněte GridView z panelu nástrojů na Designer. Nastavte Objekt GridView ID na ProductsGrid a z jeho inteligentní značky zvolte, že se má vytvořit vazba na nový objekt ObjectDataSource s názvem ProductsDataSource. Nakonfigurujte ObjectDataSource tak, aby načítal jeho data z ProductsBLL metody třídy s GetProducts .

Konfigurace objektu ObjectDataSource pro použití třídy ProductsBLL

Obrázek 2: Konfigurace objektu ObjectDataSource pro použití ProductsBLL třídy (kliknutím zobrazíte obrázek v plné velikosti)

Načtení produktových dat pomocí metody GetProducts

Obrázek 3: Načtení dat o produktu pomocí GetProducts metody (kliknutím zobrazíte obrázek v plné velikosti)

Stejně jako GridView i funkce úprav ObjectDataSource jsou navrženy tak, aby fungovaly na základě jednotlivých řádků. Abychom mohli aktualizovat sadu záznamů, budeme muset napsat trochu kódu do třídy kódu na pozadí ASP.NET stránky, která data v dávce předá do BLL. Proto nastavte rozevírací seznamy na kartách OBJECTDataSource s UPDATE, INSERT a DELETE na (None). Dokončete průvodce kliknutím na Dokončit.

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 Konfigurací zdroje dat by deklarativní kód ObjectDataSource měl vypadat takto:

<asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>

Dokončení průvodce Konfigurovat zdroj dat také způsobí, že Visual Studio vytvoří BoundFields a CheckBoxField pro pole dat produktu v GridView. Pro účely tohoto kurzu povolíte uživateli pouze zobrazení a úpravu názvu produktu, kategorie, ceny a stavu ukončení produktu. Odeberte všechna pole kromě ProductNamepolí , CategoryName, UnitPricea Discontinued a přejmenujte HeaderText vlastnosti prvních tří polí na Produkt, Kategorie a Cena. Nakonec zaškrtněte políčka Povolit stránkování a Povolit řazení v inteligentní značce GridView.

V tomto okamžiku GridView má tři BoundFields (ProductName, CategoryNamea UnitPrice) a CheckBoxField (Discontinued). Tato čtyři pole musíme převést na TemplateFields a pak přesunout rozhraní pro úpravy z pole TemplateField do EditItemTemplate jeho ItemTemplatepole .

Poznámka

Vytváření a přizpůsobení polí šablon jsme prozkoumali v kurzu Přizpůsobení rozhraní pro úpravu dat . Projdeme si kroky převodu BoundFields a CheckBoxField na TemplateFields a definování jejich rozhraní pro úpravy v jejich ItemTemplate polích, ale pokud se zaseknete nebo potřebujete osvěžit, neváhejte se vrátit k tomuto dřívějšímu kurzu.

V inteligentní značce GridView kliknutím na odkaz Upravit sloupce otevřete dialogové okno Pole. Potom vyberte jednotlivá pole a klikněte na odkaz Převést toto pole na TemplateField.

Převeďte existující BoundFields a CheckBoxField na TemplateField.

Obrázek 5: Převod existujících BoundFields a CheckBoxField na TemplateField

Teď, když je každé pole pole TemplateField, jsme připraveni přesunout rozhraní pro úpravy z EditItemTemplate s na ItemTemplate s.

Krok 2: VytvořeníProductName rozhraní aUnitPriceDiscontinued Úpravy rozhraní

ProductNameVytváření rozhraní , UnitPricea Discontinued úpravy jsou tématem tohoto kroku a jsou poměrně jednoduché, protože každé rozhraní je již definováno v TemplateField s EditItemTemplate. CategoryName Vytvoření rozhraní pro úpravy je trochu složitější, protože potřebujeme vytvořit rozevírací seznam použitelných kategorií. Toto CategoryName rozhraní pro úpravy je řešeno v kroku 3.

Začněme polem ProductName TemplateField. Klikněte na odkaz Upravit šablony z inteligentní značky GridView a přejděte k podrobnostem TemplateField ProductName s EditItemTemplate. Vyberte TextBox, zkopírujte ho do schránky a vložte ho ProductName do pole TemplateField s ItemTemplate. Změňte vlastnost TextBox s ID na ProductName.

Dále přidejte RequiredFieldValidator do ItemTemplate , abyste zajistili, že uživatel zadá hodnotu pro název každého produktu. ControlToValidate Nastavte vlastnost na ProductName, ErrorMessage vlastnost na Hodnotu Musíte zadat název produktu. Text a vlastnost *. Po přidání těchto položek do ItemTemplateby vaše obrazovka měla vypadat podobně jako na obrázku 6.

Pole Šablony ProductName teď obsahuje TextBox a RequiredFieldValidator.

Obrázek 6: Pole ProductName Šablony teď obsahuje TextBox a RequiredFieldValidator (kliknutím zobrazíte obrázek v plné velikosti)

UnitPrice Pro rozhraní pro úpravy začněte zkopírováním textového pole z do EditItemTemplateItemTemplate. Dále umístěte $ před TextBox a nastavte jeho ID vlastnost na UnitPrice a jeho Columns vlastnost na 8 .

Přidejte také CompareValidator k UnitPrice hodnotě s ItemTemplate , abyste zajistili, že hodnota zadaná uživatelem je platná hodnota měny větší nebo rovna 0,00 USD. Nastavte vlastnost validátoru ControlToValidate na JednotkovouCena, jeho ErrorMessage vlastnost na Hodnotu Musíte zadat platnou hodnotu měny. Vyněžte symboly měny, jeho Text vlastnost *, Type vlastnost Currency, vlastnost Operator na GreaterThanEquala ValueToCompare vlastnost 0 .

Přidejte CompareValidator, abyste zajistili, že zadaná cena je nezáporná hodnota měny.

Obrázek 7: Přidání compareValidatoru pro zajištění, že zadaná cena je nezáporná hodnota měny (kliknutím zobrazíte obrázek v plné velikosti)

Discontinued Pro TemplateField můžete použít CheckBox, který je již definován v objektu ItemTemplate. Jednoduše nastavte jeho ID hodnotu na Discontinued a jeho Enabled vlastnost na true.

Krok 3: VytvořeníCategoryNamerozhraní pro úpravy

Rozhraní pro úpravy v CategoryName TemplateField s EditItemTemplate obsahuje TextBox, který zobrazuje hodnotu datového CategoryName pole. Musíme ho nahradit rozevíracím seznamem, který obsahuje seznam možných kategorií.

Poznámka

Kurz Přizpůsobení rozhraní pro úpravu dat obsahuje důkladnější a ucelenější diskuzi o přizpůsobení šablony tak, aby obsahovala rozevírací seznam, na rozdíl od textového pole. Po dokončení zde uvedených kroků se zobrazí tersely. Podrobnější přehled o vytváření a konfiguraci kategorií DropDownList najdete v kurzu Přizpůsobení rozhraní pro úpravu dat .

Přetáhněte rozevírací seznam z panelu nástrojů do CategoryName pole TemplateField s ItemTemplatea nastavte jeho ID hodnotu na Categories. V tomto okamžiku bychom obvykle definovali zdroj dat DropDownLists prostřednictvím jeho inteligentní značky a vytvořili nový ObjectDataSource. To však přidá ObjectDataSource v rámci ItemTemplate, což bude mít za následek ObjectDataSource instance vytvořené pro každý řádek GridView. Místo toho vytvořte ObjectDataSource mimo GridView s TemplateFields. Ukončete úpravy šablony a přetáhněte ObjectDataSource z panelu nástrojů do Designer pod ProductsDataSource ObjectDataSource. Pojmenujte nový ObjectDataSource CategoriesDataSource a nakonfigurujte ho tak, aby používal metodu CategoriesBLL třídy s GetCategories .

Nakonfigurujte ObjectDataSource tak, aby používal třídu CategoriesBLL.

Obrázek 8: Konfigurace objektu ObjectDataSource pro použití CategoriesBLL třídy (kliknutím zobrazíte obrázek v plné velikosti)

Načtení dat kategorie pomocí metody GetCategories

Obrázek 9: Načtení dat kategorie pomocí GetCategories metody (kliknutím zobrazíte obrázek v plné velikosti)

Vzhledem k tomu, že se tento ObjectDataSource používá pouze k načtení dat, nastavte rozevírací seznamy na kartách UPDATE a DELETE na (None). Dokončete průvodce kliknutím na Dokončit.

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

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

Po dokončení průvodce CategoriesDataSource by deklarativní kód s měl vypadat takto:

<asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>

CategoriesDataSource S vytvořeným a nakonfigurovaným objektem se vraťte do CategoryName pole TemplateField a ItemTemplate z inteligentní značky DropDownList s klikněte na odkaz Zvolit zdroj dat. V průvodci Konfigurací zdroje dat vyberte CategoriesDataSource možnost z prvního rozevíracího seznamu a zvolte, že CategoryName se má použít pro zobrazení a CategoryID jako hodnotu.

Vytvoření vazby rozevíracího seznamu s kategoriemiDataSource

Obrázek 11: Vytvoření vazby rozevíracího seznamu k obrázku CategoriesDataSource (kliknutím zobrazíte obrázek v plné velikosti)

V tomto okamžiku Categories rozevírací seznam obsahuje všechny kategorie, ale zatím automaticky nevybere příslušnou kategorii pro produkt vázaný na řádek GridView. Abychom toho dosáhli, musíme nastavit Categories hodnotu DropDownList na SelectedValue hodnotu produktu CategoryID . Klikněte na odkaz Upravit vazby dat z inteligentní značky DropDownList a přidružte SelectedValue vlastnost k datovému CategoryID poli, jak je znázorněno na obrázku 12.

Vytvoření vazby hodnoty Product s CategoryID k vlastnosti DropDownList s SelectedValue

Obrázek 12: Vytvoření vazby hodnoty Product s CategoryID na vlastnost DropDownList s SelectedValue

Zbývá poslední problém: Pokud produkt nemá zadanou CategoryID hodnotu, výsledkem příkazu databinding pro SelectedValue bude výjimka. Je to proto, že DropDownList obsahuje pouze položky pro kategorie a nenabízí možnost pro produkty, které mají NULL hodnotu databáze pro CategoryID. Chcete-li tento problém vyřešit, nastavte vlastnost true DropDownList na AppendDataBoundItems a přidejte novou položku do rozevíracího seznamu, přičemž vynecháte Value vlastnost z deklarativní syntaxe. To znamená, že Categories deklarativní syntaxe DropDownList s vypadá takto:

<asp:DropDownList ID="Categories" runat="server" AppendDataBoundItems="True" 
    DataSourceID="CategoriesDataSource" DataTextField="CategoryName" 
    DataValueField="CategoryID" SelectedValue='<%# Bind("CategoryID") %>'>
    <asp:ListItem Value=">-- Select One --</asp:ListItem>
</asp:DropDownList>

Všimněte si, že <asp:ListItem Value=""> je atribut Value -- Select One -- explicitně nastavený na prázdný řetězec. Projděte si kurz Přizpůsobení rozhraní pro úpravu dat, kde najdete podrobnější diskuzi o tom, proč je tato další položka rozevíracího Value seznamu potřebná ke zpracování NULL případu a proč je přiřazení vlastnosti k prázdnému řetězci nezbytné.

Poznámka

Tady je potenciální problém s výkonem a škálovatelností, který stojí za zmínku. Vzhledem k tomu, že každý řádek má DropDownList, který používá CategoriesDataSource jako zdroj dat metodu CategoriesBLL třídy s GetCategories bude volána n krát za návštěvu stránky, kde n je počet řádků v GridView. Výsledkem těchto n volání je GetCategoriesn dotazů na databázi. Tento dopad na databázi by se mohl zmenšit uložením vrácených kategorií do mezipaměti pro jednotlivé požadavky nebo prostřednictvím vrstvy ukládání do mezipaměti pomocí závislosti mezipaměti SQL nebo velmi krátké vypršení platnosti založeného na čase.

Krok 4: Dokončení rozhraní pro úpravy

Provedli jsme řadu změn v šablonách GridView s bez pozastavení, abychom viděli náš průběh. Udělejte si chvilku a podívejte se na průběh v prohlížeči. Jak ukazuje obrázek 13, každý řádek se vykresluje pomocí svého ItemTemplate, který obsahuje rozhraní pro úpravy buňky s.

Každý řádek GridView je upravitelný.

Obrázek 13: Každý řádek GridView je upravitelný (kliknutím zobrazíte obrázek v plné velikosti)

V tuto chvíli bychom se měli postarat o několik menších problémů s formátováním. Nejprve si všimněte, že UnitPrice hodnota obsahuje čtyři desetinné čárky. Pokud chcete tento problém vyřešit, vraťte se do UnitPrice pole TemplateField s ItemTemplate a z inteligentní značky TextBox s klikněte na odkaz Upravit vazby dat. Dále určete, že Text vlastnost má být naformátovaná jako číslo.

Formátování vlastnosti Text jako čísla

Obrázek 14: Formátování Text vlastnosti jako čísla

Za druhé zarovnejte zaškrtávací políčko ve sloupci na Discontinued střed (místo toho, aby bylo zarovnané doleva). Klikněte na Upravit sloupce z inteligentní značky GridView a vyberte Discontinued TemplateField ze seznamu polí v levém dolním rohu. Přejděte k ItemStyle podrobnostem HorizontalAlign a nastavte vlastnost Na střed, jak je znázorněno na obrázku 15.

Vycentrovat zaškrtávací políčko Ukončeno

Obrázek 15: Na střed zaškrtávacího Discontinued políčka

Dále přidejte na stránku ovládací prvek ValidationSummary a nastavte jeho ShowMessageBox vlastnost na true a jeho ShowSummary vlastnost na false. Přidejte také ovládací prvky Button Web, které po kliknutí aktualizují změny uživatele. Konkrétně přidejte dva ovládací prvky Button Web, jeden nad GridView a jeden pod něj, přičemž oba ovládací prvky Text vlastnosti nastaví na Aktualizovat produkty .

Vzhledem k tomu, GridView s editing rozhraní je definován v jeho TemplateFields ItemTemplate s, EditItemTemplate jsou s nadbytečné a mohou být odstraněny.

Po provedení výše uvedených změn formátování, přidání ovládacích prvků Tlačítko a odebrání nepotřebných EditItemTemplate s by deklarativní syntaxe stránky měla vypadat takto:

<p>
    <asp:Button ID="UpdateAllProducts1" runat="server" Text="Update Products" />
</p>
<p>
    <asp:GridView ID="ProductsGrid" runat="server" AutoGenerateColumns="False" 
        DataKeyNames="ProductID" DataSourceID="ProductsDataSource" 
        AllowPaging="True" AllowSorting="True">
        <Columns>
            <asp:TemplateField HeaderText="Product" SortExpression="ProductName">
                <ItemTemplate>
                    <asp:TextBox ID="ProductName" runat="server" 
                        Text='<%# Bind("ProductName") %>'></asp:TextBox>
                    <asp:RequiredFieldValidator ID="RequiredFieldValidator1" 
                        ControlToValidate="ProductName"
                        ErrorMessage="You must provide the product's name." 
                        runat="server">*</asp:RequiredFieldValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Category" 
                SortExpression="CategoryName">
                <ItemTemplate>
                    <asp:DropDownList ID="Categories" runat="server" 
                        AppendDataBoundItems="True" 
                        DataSourceID="CategoriesDataSource"
                        DataTextField="CategoryName" 
                        DataValueField="CategoryID" 
                        SelectedValue='<%# Bind("CategoryID") %>'>
                        <asp:ListItem>-- Select One --</asp:ListItem>
                    </asp:DropDownList>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Price" 
                SortExpression="UnitPrice">
                <ItemTemplate>
                    $<asp:TextBox ID="UnitPrice" runat="server" Columns="8" 
                        Text='<%# Bind("UnitPrice", "{0:N}") %>'></asp:TextBox>
                    <asp:CompareValidator ID="CompareValidator1" runat="server" 
                        ControlToValidate="UnitPrice"
                        ErrorMessage="You must enter a valid currency value. 
                                      Please omit any currency symbols."
                        Operator="GreaterThanEqual" Type="Currency" 
                        ValueToCompare="0">*</asp:CompareValidator>
                </ItemTemplate>
            </asp:TemplateField>
            <asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
                <ItemTemplate>
                    <asp:CheckBox ID="Discontinued" runat="server" 
                        Checked='<%# Bind("Discontinued") %>' />
                </ItemTemplate>
                <ItemStyle HorizontalAlign="Center" />
            </asp:TemplateField>
        </Columns>
    </asp:GridView>
</p>
<p>
    <asp:Button ID="UpdateAllProducts2" runat="server" Text="Update Products" />
    <asp:ObjectDataSource ID="ProductsDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetProducts" TypeName="ProductsBLL">
    </asp:ObjectDataSource>
    <asp:ObjectDataSource ID="CategoriesDataSource" runat="server" 
        OldValuesParameterFormatString="original_{0}"
        SelectMethod="GetCategories" TypeName="CategoriesBLL">
    </asp:ObjectDataSource>
    <asp:ValidationSummary ID="ValidationSummary1" runat="server" 
        ShowMessageBox="True" ShowSummary="False" />
</p>

Obrázek 16 znázorňuje tuto stránku při zobrazení v prohlížeči po přidání ovládacích prvků Button Web a provedení změn formátování.

Stránka teď obsahuje dvě tlačítka pro aktualizaci produktů.

Obrázek 16: Stránka teď obsahuje dvě tlačítka aktualizace produktů (kliknutím zobrazíte obrázek v plné velikosti)

Krok 5: Aktualizace produktů

Když uživatel navštíví tuto stránku, provede změny a potom klikne na jedno ze dvou tlačítek Aktualizovat produkty. V tomto okamžiku musíme nějak uložit uživatelem zadané hodnoty pro každý řádek do ProductsDataTable instance a pak je předat metodě BLL, která pak předá danou ProductsDataTable instanci metodě DAL s UpdateWithTransaction . Metoda UpdateWithTransaction , kterou jsme vytvořili v předchozím kurzu, zajišťuje, že dávka změn bude aktualizována jako atomická operace.

Vytvořte metodu s názvem BatchUpdate in BatchUpdate.aspx.cs a přidejte následující kód:

private void BatchUpdate()
{
    // Enumerate the GridView's Rows collection and create a ProductRow
    ProductsBLL productsAPI = new ProductsBLL();
    Northwind.ProductsDataTable products = productsAPI.GetProducts();
    foreach (GridViewRow gvRow in ProductsGrid.Rows)
    {
        // Find the ProductsRow instance in products that maps to gvRow
        int productID = Convert.ToInt32(ProductsGrid.DataKeys[gvRow.RowIndex].Value);
        Northwind.ProductsRow product = products.FindByProductID(productID);
        if (product != null)
        {
            // Programmatically access the form field elements in the 
            // current GridViewRow
            TextBox productName = (TextBox)gvRow.FindControl("ProductName");
            DropDownList categories = 
                (DropDownList)gvRow.FindControl("Categories");
            TextBox unitPrice = (TextBox)gvRow.FindControl("UnitPrice");
            CheckBox discontinued = 
                (CheckBox)gvRow.FindControl("Discontinued");
            // Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim();
            if (categories.SelectedIndex == 0) 
                product.SetCategoryIDNull(); 
            else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue);
            if (unitPrice.Text.Trim().Length == 0) 
                product.SetUnitPriceNull(); 
            else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text);
            product.Discontinued = discontinued.Checked;
        }
    }
    // Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products);
}

Tato metoda začíná tím, že prostřednictvím volání metody BLL s GetProducts vrátí všechny produkty zpětProductsDataTable. Potom vytvoří ProductGrid výčet kolekce GridView sRows. Kolekce Rows obsahuje GridViewRow instanci pro každý řádek zobrazený v GridView. Vzhledem k tomu, že na stránce zobrazujeme maximálně deset řádků, nebude kolekce GridView obsahovat Rows více než deset položek.

Pro každý řádek ProductID se vezme z DataKeys kolekce a vybere se příslušný ProductsRow řádek z ProductsDataTable. Na čtyři vstupní ovládací prvky TemplateField se programově odkazují a jejich hodnoty jsou přiřazeny vlastnostem ProductsRow instance s. Po použití hodnot řádků gridView k aktualizaci ProductsDataTablese předá do metody BLL s UpdateWithTransaction , která, jak jsme viděli v předchozím kurzu, jednoduše zavolá dolů do metody DAL s UpdateWithTransaction .

Algoritmus dávkové aktualizace použitý pro tento kurz aktualizuje každý řádek v objektu ProductsDataTable , který odpovídá řádku v GridView, bez ohledu na to, zda byly změněny informace o produktu. I když tyto nevidomé aktualizace obvykle nejsou problém s výkonem, můžou vést k nadbytečným záznamům, pokud auditujete změny v tabulce databáze. V kurzu Provádění služby Batch Aktualizace jsme prozkoumali rozhraní dávkové aktualizace pomocí DataListu a přidali jsme kód, který by aktualizoval pouze záznamy, které byly skutečně změněny uživatelem. V případě potřeby můžete použít techniky z provádění batch Aktualizace k aktualizaci kódu v tomto kurzu.

Poznámka

Při vazbě zdroje dat na GridView prostřednictvím jeho inteligentní značky Visual Studio automaticky přiřadí primární hodnoty klíče zdroje dat gridView s DataKeyNames vlastnost. Pokud jste nevytvořili vazbu ObjectDataSource na GridView prostřednictvím inteligentní značky GridView s, jak je popsáno v kroku 1, budete muset ručně nastavit vlastnost GridView s DataKeyNames na ProductID, abyste získali přístup k ProductID hodnotě pro každý řádek prostřednictvím DataKeys kolekce.

Kód použitý v BatchUpdate se podobá kódu použitému v metodách BLL s UpdateProduct . Hlavní rozdíl spočívá v tom, že v UpdateProduct metodách je z architektury načtena pouze jedna ProductRow instance. Kód, který přiřazuje vlastnosti objektu ProductRow , je stejný mezi UpdateProducts metodami a kódem v rámci foreach smyčky v BatchUpdate, stejně jako celkový vzor.

K dokončení tohoto kurzu potřebujeme metodu BatchUpdate vyvolat, když kliknete na tlačítko Aktualizovat produkty. Vytvořte obslužné rutiny událostí pro Click události těchto dvou ovládacích prvků Button a přidejte do obslužných rutin událostí následující kód:

BatchUpdate();
ClientScript.RegisterStartupScript(this.GetType(), "message", 
    "alert('The products have been updated.');", true);

Nejprve se zavolá na BatchUpdate. Dále se použije k vložení JavaScriptu, ClientScript property který zobrazí messagebox s textem Produkty byly aktualizovány.

Chvíli si tento kód otestujte. Přejděte BatchUpdate.aspx přes prohlížeč, upravte několik řádků a klikněte na jedno z tlačítek Aktualizovat produkty. Za předpokladu, že nedošlo k žádným chybám ověření vstupu, by se mělo zobrazit okno zprávy s textem Produkty byly aktualizovány. Pokud chcete ověřit atomicitu aktualizace, zvažte přidání náhodného CHECK omezení, například takového, které zakáže UnitPrice hodnoty 1234,56. Potom v BatchUpdate.aspxsouboru upravte několik záznamů a nezapomeňte nastavit jeden z hodnot součinu UnitPrice na hodnotu Zakázáno ( 1234.56 ). Výsledkem by měla být chyba při kliknutí na Aktualizovat produkty s dalšími změnami během této dávkové operace vrácenými zpět na původní hodnoty.

AlternativníBatchUpdatemetoda

Metoda BatchUpdate , kterou jsme právě prozkoumali, načte všechny produkty z metody BLL s GetProducts a pak aktualizuje pouze ty záznamy, které se zobrazí v GridView. Tento přístup je ideální, pokud GridView nepoužívá stránkování, ale pokud ano, může existovat stovky, tisíce nebo desítky tisíc produktů, ale pouze deset řádků v GridView. V takovém případě je získání všech produktů z databáze pouze k úpravě 10 z nich méně než ideální.

Pro tyto typy situací zvažte použití následující BatchUpdateAlternate metody:

private void BatchUpdateAlternate()
{
    // Enumerate the GridView's Rows collection and create a ProductRow
    ProductsBLL productsAPI = new ProductsBLL();
    Northwind.ProductsDataTable products = new Northwind.ProductsDataTable();
    foreach (GridViewRow gvRow in ProductsGrid.Rows)
    {
        // Create a new ProductRow instance
        int productID = Convert.ToInt32(ProductsGrid.DataKeys[gvRow.RowIndex].Value);
        
        Northwind.ProductsDataTable currentProductDataTable = 
            productsAPI.GetProductByProductID(productID);
        if (currentProductDataTable.Rows.Count > 0)
        {
            Northwind.ProductsRow product = currentProductDataTable[0];
            // Programmatically access the form field elements in the 
            // current GridViewRow
            TextBox productName = (TextBox)gvRow.FindControl("ProductName");
            DropDownList categories = 
                (DropDownList)gvRow.FindControl("Categories");
            TextBox unitPrice = (TextBox)gvRow.FindControl("UnitPrice");
            CheckBox discontinued = 
                (CheckBox)gvRow.FindControl("Discontinued");
            // Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim();
            if (categories.SelectedIndex == 0) 
                product.SetCategoryIDNull(); 
            else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue);
            if (unitPrice.Text.Trim().Length == 0) 
                product.SetUnitPriceNull(); 
            else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text);
            product.Discontinued = discontinued.Checked;
            // Import the ProductRow into the products DataTable
            products.ImportRow(product);
        }
    }
    // Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products);
}

BatchMethodAlternate Začíná vytvořením nového prázdného ProductsDataTable souboru s názvem products. Pak prochází kolekci GridView s Rows a pro každý řádek získá konkrétní informace o produktu pomocí metody BLL s GetProductByProductID(productID) . Načtená ProductsRow instance má své vlastnosti aktualizované stejným způsobem jako BatchUpdate, ale po aktualizaci řádku se importuje do products``ProductsDataTable prostřednictvím metody DataTable sImportRow(DataRow).

Po dokončení foreach smyčky obsahuje products jednu ProductsRow instanci pro každý řádek v GridView. Vzhledem k tomu, že každá z ProductsRow instancí byla přidána do products (místo aktualizace), pokud je UpdateWithTransaction slepě předáme metodě ProductsTableAdapter , pokusí se každý ze záznamů vložit do databáze. Místo toho musíme určit, že každý z těchto řádků byl změněn (nikoli přidán).

Toho lze dosáhnout přidáním nové metody do BLL s názvem UpdateProductsWithTransaction. UpdateProductsWithTransaction, jak je znázorněno níže, nastaví RowState každou instanci ProductsRow v objektu ProductsDataTable do Modified a pak předá ProductsDataTable do metody DAL s UpdateWithTransaction .

public int UpdateProductsWithTransaction(Northwind.ProductsDataTable products)
{
    // Mark each product as Modified
    products.AcceptChanges();
    foreach (Northwind.ProductsRow product in products)
        product.SetModified();
    // Update the data via a transaction
    return UpdateWithTransaction(products);
}

Souhrn

GridView poskytuje integrované možnosti úprav po řádcích, ale postrádá podporu pro vytváření plně upravitelných rozhraní. Jak jsme viděli v tomto kurzu, taková rozhraní jsou možná, ale vyžadují trochu práce. Pokud chcete vytvořit Objekt GridView, kde je možné upravovat každý řádek, musíme převést pole GridView s na TemplateFields a definovat rozhraní pro úpravy v rámci ItemTemplate s. Kromě toho, Update All -type Button Web ovládací prvky musí být přidány na stránku, odděleně od GridView. Tyto obslužné rutiny událostí Tlačítka Click musí vytvořit výčet GridView Rows s kolekce, uložit změny v objektu ProductsDataTablea předat aktualizované informace do příslušné metody BLL.

V dalším kurzu se dozvíte, jak vytvořit rozhraní pro dávkové odstranění. Konkrétně každý řádek GridView bude obsahovat zaškrtávací políčko a místo tlačítek Aktualizovat všechny typy budeme mít tlačítka Odstranit vybrané řádky.

Všechno nejlepší na 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 zastihnout na mitchell@4GuysFromRolla.comadrese . nebo prostřednictvím jeho blogu, který najdete na adrese http://ScottOnWriting.NET.

Zvláštní poděkování

Tato série kurzů byla zkontrolována mnoha užitečnými recenzenty. Hlavními recenzenty pro tento kurz byli Teresa Murphy a David Suru. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.