Provádění dávkových aktualizací (C#)
Kliknutím na tlačítko Aktualizovat vše na stránce se dozvíte, jak vytvořit plně upravitelný datový seznam, ve kterém jsou všechny jeho položky v režimu úprav a jejichž hodnoty se dají uložit.
Úvod
V předchozím kurzu jsme se zabývali tím, jak vytvořit DataList na úrovni položky. Podobně jako u standardního upravitelného objektu GridView obsahovala každá položka v Seznamu dat tlačítko Upravit, které by po kliknutí na položku bylo upravitelné. I když tyto úpravy na úrovni položek fungují dobře u dat, která se aktualizují jenom občas, některé scénáře použití vyžadují, aby uživatel upravil mnoho záznamů. Pokud uživatel potřebuje upravit desítky záznamů a je nucen kliknout na Upravit, provést změny a u každého z nich kliknout na Aktualizovat, může množství kliknutí omezit jeho produktivitu. V takových situacích je lepší poskytnout plně upravitelný datový seznam, kde jsou všechny jeho položky v režimu úprav a jehož hodnoty lze upravit kliknutím na tlačítko Aktualizovat vše na stránce (viz Obrázek 1).
Obrázek 1: Každou položku v plně upravitelném seznamu dat je možné upravit (kliknutím zobrazíte obrázek v plné velikosti).
V tomto kurzu prozkoumáme, jak uživatelům umožnit aktualizovat informace o dodavatelích adres pomocí plně upravitelného seznamu DataList.
Krok 1: Vytvoření upravitelného uživatelského rozhraní v DataList s ItemTemplate
V předchozím kurzu, kde jsme vytvořili standardní upravitelný datový seznam na úrovni položek, jsme použili dvě šablony:
ItemTemplate
obsahoval uživatelské rozhraní jen pro čtení (ovládací prvky Label Web pro zobrazení názvu a ceny jednotlivých produktů).EditItemTemplate
obsahoval uživatelské rozhraní režimu úprav (dva ovládací prvky TextBox Web).
Vlastnost DataList s EditItemIndex
určuje, co DataListItem
se (pokud existuje) vykresluje pomocí EditItemTemplate
. Konkrétně se DataListItem
hodnota, jejíž ItemIndex
hodnota odpovídá vlastnosti DataList s EditItemIndex
, vykresluje pomocí EditItemTemplate
. Tento model funguje dobře, když lze současně upravovat jenom jednu položku, ale při vytváření plně upravitelného seznamu Dat se rozpadá.
Pro plně upravitelný DataList chceme, aby se všechny s DataListItem
vykreslovat pomocí upravitelného rozhraní. Nejjednodušším způsobem, jak toho dosáhnout, je definovat upravitelné rozhraní v .ItemTemplate
Pro úpravu informací o adrese dodavatele obsahuje upravitelné rozhraní název dodavatele jako text a pak textová pole pro hodnoty adresy, města a země/oblasti.
Začněte otevřením BatchUpdate.aspx
stránky, přidáním ovládacího prvku DataList a nastavením jeho ID
vlastnosti na Suppliers
. Z inteligentní značky DataList zvolte přidání nového ovládacího prvku ObjectDataSource s názvem SuppliersDataSource
.
Obrázek 2: Vytvoření nového objektuDataSource s názvem SuppliersDataSource
(kliknutím zobrazíte obrázek v plné velikosti)
Nakonfigurujte ObjectDataSource tak, aby načítal data pomocí SuppliersBLL
metody třídy s GetSuppliers()
(viz Obrázek 3). Stejně jako v předchozím kurzu nebudeme aktualizovat informace o dodavateli prostřednictvím ObjectDataSource, ale budeme pracovat přímo s vrstvou obchodní logiky. Proto nastavte rozevírací seznam na (Žádný) na kartě UPDATE (viz Obrázek 4).
Obrázek 3: Načtení informací o dodavateli GetSuppliers()
pomocí metody (kliknutím zobrazíte obrázek v plné velikosti)
Obrázek 4: Nastavení seznamu Drop-Down na (Žádný) na kartě AKTUALIZACE (kliknutím zobrazíte obrázek v plné velikosti)
Po dokončení průvodce Visual Studio automaticky vygeneruje dataList pro ItemTemplate
zobrazení všech datových polí vrácených zdrojem dat v ovládacím prvku Label Web. Tuto šablonu musíme upravit tak, aby místo toho poskytovala rozhraní pro úpravy. Objekt ItemTemplate
lze přizpůsobit prostřednictvím Designer pomocí možnosti Upravit šablony z inteligentní značky DataList nebo přímo prostřednictvím deklarativní syntaxe.
Udělejte si chvilku a vytvořte rozhraní pro úpravy, které zobrazí jméno dodavatele jako text, ale bude obsahovat textová pole pro adresu dodavatele, město a zemi/oblast. Po provedení těchto změn by deklarativní syntaxe stránky měla vypadat nějak takto:
<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
DataSourceID="SuppliersDataSource">
<ItemTemplate>
<h4><asp:Label ID="CompanyNameLabel" runat="server"
Text='<%# Eval("CompanyName") %>' /></h4>
<table border="0">
<tr>
<td class="SupplierPropertyLabel">Address:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Address" runat="server"
Text='<%# Eval("Address") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">City:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="City" runat="server"
Text='<%# Eval("City") %>' />
</td>
</tr>
<tr>
<td class="SupplierPropertyLabel">Country:</td>
<td class="SupplierPropertyValue">
<asp:TextBox ID="Country" runat="server"
Text='<%# Eval("Country") %>' />
</td>
</tr>
</table>
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>
Poznámka
Stejně jako v předchozím kurzu musí mít datový seznam v tomto kurzu povolený stav zobrazení.
V části ItemTemplate
Používám dvě nové třídy CSS, SupplierPropertyLabel
a SupplierPropertyValue
, které byly přidány do Styles.css
třídy a nakonfigurovány tak, aby používaly stejné nastavení stylu jako ProductPropertyLabel
třídy a ProductPropertyValue
CSS.
.ProductPropertyLabel, .SupplierPropertyLabel
{
font-weight: bold;
text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
padding-right: 35px;
}
Po provedení těchto změn přejděte na tuto stránku prostřednictvím prohlížeče. Jak znázorňuje obrázek 5, každá položka DataList zobrazuje název dodavatele jako text a používá textová pole k zobrazení adresy, města a země/oblasti.
Obrázek 5: Každý dodavatel v seznamu DataList je upravitelný (kliknutím zobrazíte obrázek v plné velikosti)
Krok 2: Přidání tlačítka Aktualizovat vše
I když má každý dodavatel na obrázku 5 v textovém poli zobrazená pole adresa, město a země/oblast, momentálně není k dispozici tlačítko Aktualizovat. Místo tlačítka Aktualizovat pro každou položku s plně upravitelnými položkami DataLists je obvykle na stránce jedno tlačítko Aktualizovat vše, které po kliknutí aktualizuje všechny záznamy v seznamu DataList. Pro účely tohoto kurzu přidáme dvě tlačítka Aktualizovat vše – jedno v horní části stránky a jedno dole (i když kliknutí na jedno z těchto tlačítek bude mít stejný účinek).
Začněte přidáním webového ovládacího prvku Button (Tlačítko) nad DataList a nastavte jeho ID
vlastnost na UpdateAll1
. Dále přidejte druhý webový ovládací prvek Button (Webové tlačítko) pod DataList a nastavte ho ID
na UpdateAll2
. Text
Nastavte vlastnosti těchto dvou tlačítek na Aktualizovat vše. Nakonec vytvořte obslužné rutiny událostí pro obě události tlačítka Click
. Místo duplikování logiky aktualizace v jednotlivých obslužných rutinách událostí pojďme tuto logiku refaktorovat na třetí metodu, s tím, UpdateAllSupplierAddresses
že obslužné rutiny událostí jednoduše vyvolávají tuto třetí metodu.
protected void UpdateAll1_Click(object sender, EventArgs e)
{
UpdateAllSupplierAddresses();
}
protected void UpdateAll2_Click(object sender, EventArgs e)
{
UpdateAllSupplierAddresses();
}
private void UpdateAllSupplierAddresses()
{
// TODO: Write code to update _all_ of the supplier addresses in the DataList
}
Obrázek 6 znázorňuje stránku po přidání tlačítek Aktualizovat vše.
Obrázek 6: Na stránku byla přidána dvě tlačítka Aktualizovat všechny (kliknutím zobrazíte obrázek v plné velikosti)
Krok 3: Aktualizace informací o adrese všech dodavatelů
Se všemi položkami DataList zobrazují rozhraní pro úpravy a s přidáním tlačítek Aktualizovat vše, vše, co zbývá, je napsání kódu pro provedení dávkové aktualizace. Konkrétně potřebujeme projít položky Třídy s a volat metodu SuppliersBLL
třídy s UpdateSupplierAddress
pro každou z nich.
Ke kolekci DataListItem
instancí, které jsou součástí objektu DataList, je možné přistupovat prostřednictvím vlastnosti DataList sItems
. S odkazem na DataListItem
objekt můžeme získat odpovídající SupplierID
z DataKeys
kolekce a programově odkazovat na ovládací prvky TextBox Web v rámci objektu ItemTemplate
, jak ukazuje následující kód:
private void UpdateAllSupplierAddresses()
{
// Create an instance of the SuppliersBLL class
SuppliersBLL suppliersAPI = new SuppliersBLL();
// Iterate through the DataList's items
foreach (DataListItem item in Suppliers.Items)
{
// Get the supplierID from the DataKeys collection
int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);
// Read in the user-entered values
TextBox address = (TextBox)item.FindControl("Address");
TextBox city = (TextBox)item.FindControl("City");
TextBox country = (TextBox)item.FindControl("Country");
string addressValue = null, cityValue = null, countryValue = null;
if (address.Text.Trim().Length > 0)
addressValue = address.Text.Trim();
if (city.Text.Trim().Length > 0)
cityValue = city.Text.Trim();
if (country.Text.Trim().Length > 0)
countryValue = country.Text.Trim();
// Call the SuppliersBLL class's UpdateSupplierAddress method
suppliersAPI.UpdateSupplierAddress
(supplierID, addressValue, cityValue, countryValue);
}
}
Když uživatel klikne na jedno z tlačítek Aktualizovat vše, UpdateAllSupplierAddresses
metoda prochází všechna DataListItem
tlačítka v Suppliers
DataList a volá metodu SuppliersBLL
třídy s UpdateSupplierAddress
a předá odpovídající hodnoty. Nezadaná hodnota pro adresu, město nebo zemi/oblast je hodnota Nothing
do (nikoli prázdný řetězec), což vede k UpdateSupplierAddress
databázi NULL
pro pole podkladových záznamů.
Poznámka
Pro vylepšení můžete chtít na stránku přidat ovládací prvek Status Label Web, který po provedení dávkové aktualizace poskytuje potvrzovací zprávu.
Aktualizují se jenom adresy, které byly změněny.
Algoritmus dávkové aktualizace použitý v tomto kurzu volá metodu UpdateSupplierAddress
pro každého dodavatele v seznamu DataList bez ohledu na to, zda byly změněny informace o adrese. I když tyto slepé aktualizace obvykle nejsou problémem s výkonem, můžou vést k nadbytečným záznamům, pokud auditujete změny v tabulce databáze. Pokud například pomocí aktivačních událostí zaznamenáte všechny UPDATE
položky do Suppliers
tabulky auditování, pokaždé, když uživatel klikne na tlačítko Aktualizovat vše, vytvoří se pro každého dodavatele v systému nový záznam auditu bez ohledu na to, jestli uživatel provedl nějaké změny.
Třídy ADO.NET DataTable a DataAdapter jsou navrženy tak, aby podporovaly dávkové aktualizace, kdy pouze změněné, odstraněné a nové záznamy mají za následek jakoukoli komunikaci databáze. Každý řádek v tabulce DataTable má RowState
vlastnost , která označuje, zda byl řádek přidán do tabulky DataTable, odstraněn z ní, změněn nebo zůstává beze změny. Při počátečním naplnění tabulky DataTable se všechny řádky označí beze změny. Změna hodnoty libovolného sloupce řádku označí řádek jako změněný.
SuppliersBLL
Ve třídě aktualizujeme zadané informace o adrese dodavatele tak, že nejprve přečteme jeden záznam dodavatele do SuppliersDataTable
a pak nastavíme Address
hodnoty sloupce , City
a Country
pomocí následujícího kódu:
public bool UpdateSupplierAddress
(int supplierID, string address, string city, string country)
{
Northwind.SuppliersDataTable suppliers =
Adapter.GetSupplierBySupplierID(supplierID);
if (suppliers.Count == 0)
// no matching record found, return false
return false;
else
{
Northwind.SuppliersRow supplier = suppliers[0];
if (address == null)
supplier.SetAddressNull();
else
supplier.Address = address;
if (city == null)
supplier.SetCityNull();
else
supplier.City = city;
if (country == null)
supplier.SetCountryNull();
else
supplier.Country = country;
// Update the supplier Address-related information
int rowsAffected = Adapter.Update(supplier);
// Return true if precisely one row was updated,
// otherwise false
return rowsAffected == 1;
}
}
Tento kód naivně přiřadí předané hodnoty adresy, města a země/oblasti k SuppliersRow
hodnotě SuppliersDataTable
v bez ohledu na to, jestli se hodnoty změnily. Tyto úpravy způsobí, že SuppliersRow
vlastnost s RowState
se označí jako změněná. Při zavolání metody Data Access Layer Update
se zobrazí, že SupplierRow
došlo k úpravě, a proto odešle UPDATE
příkaz do databáze.
Představte si ale, že jsme do této metody přidali kód, který přiřadí předané hodnoty adresy, města a země/oblasti jenom v případě, že se liší od SuppliersRow
existujících hodnot. V případě, že jsou adresa, město a země/oblast stejné jako stávající data, neprovedou se žádné změny a SupplierRow
RowState
hodnoty zůstanou označené jako nezměněné. Čistý výsledek je, že při volání metody DAL s Update
se neprovedou žádné volání databáze, protože SuppliersRow
nebyl změněn.
Pokud chcete tuto změnu provést, nahraďte příkazy, které předané hodnoty adresy, města a země/oblasti slepě přiřazují, následujícím kódem:
// Only assign the values to the SupplierRow's column values if they differ
if (address == null && !supplier.IsAddressNull())
supplier.SetAddressNull();
else if ((address != null && supplier.IsAddressNull()) ||
(!supplier.IsAddressNull() &&
string.Compare(supplier.Address, address) != 0))
supplier.Address = address;
if (city == null && !supplier.IsCityNull())
supplier.SetCityNull();
else if ((city != null && supplier.IsCityNull()) ||
(!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0))
supplier.City = city;
if (country == null && !supplier.IsCountryNull())
supplier.SetCountryNull();
else if ((country != null && supplier.IsCountryNull()) ||
(!supplier.IsCountryNull() &&
string.Compare(supplier.Country, country) != 0))
supplier.Country = country;
S tímto přidaným kódem metoda DAL s Update
odešle UPDATE
do databáze příkaz pouze pro ty záznamy, jejichž hodnoty související s adresou se změnily.
Případně bychom mohli sledovat, jestli jsou mezi poli předané adresy a databázovými daty nějaké rozdíly, a pokud žádné neexistují, jednoduše obejít volání metody DAL s Update
. Tento přístup funguje dobře, pokud používáte přímou metodu databáze, protože přímá metoda databáze není předána SuppliersRow
instanci, jejíž RowState
kontrolu lze zkontrolovat, zda je volání databáze skutečně potřeba.
Poznámka
Při každém vyvolání UpdateSupplierAddress
metody se provede volání databáze za účelem načtení informací o aktualizovaném záznamu. Pokud pak dojde k nějakým změnám v datech, provede se další volání databáze, které aktualizuje řádek tabulky. Tento pracovní postup je možné optimalizovat vytvořením UpdateSupplierAddress
přetížení metody, které přijímá EmployeesDataTable
instanci, která obsahuje všechny změny ze BatchUpdate.aspx
stránky. Pak může provést jedno volání databáze, aby se získaly všechny záznamy z Suppliers
tabulky. Tyto dvě sady výsledků by se pak daly vyčíslit a aktualizovat se dají jenom ty záznamy, ve kterých došlo ke změnám.
Souhrn
V tomto kurzu jsme viděli, jak vytvořit plně upravitelný seznam dat, který uživateli umožňuje rychle upravit informace o adrese pro více dodavatelů. Začali jsme definováním rozhraní pro úpravy ovládacího prvku TextBox Web pro hodnoty adresy dodavatele, města a země/oblasti v DataList s ItemTemplate
. Dále jsme nad a pod dataList přidali tlačítka Aktualizovat vše. Jakmile uživatel provede změny a klikne na jedno z tlačítek Aktualizovat vše, DataListItem
zobrazí se výčet s a provede se SuppliersBLL
volání metody třídy s UpdateSupplierAddress
.
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 Zack Jones a Ken Pespisa. Chtěli byste si projít své nadcházející články na webu MSDN? Pokud ano, dejte mi řádek na mitchell@4GuysFromRolla.com.