Wykonywanie aktualizacji wsadowych (VB)
Autor: Scott Mitchell
Dowiedz się, jak utworzyć w pełni edytowalną listę danych, w której wszystkie jego elementy są w trybie edycji i których wartości można zapisać, klikając przycisk "Aktualizuj wszystko" na stronie.
Wprowadzenie
W poprzednim samouczku sprawdziliśmy, jak utworzyć element DataList na poziomie elementu. Podobnie jak w przypadku standardowego edytowalnego widoku GridView, każdy element w elemencie DataList zawierał przycisk Edytuj, który po kliknięciu sprawi, że element będzie edytowalny. Chociaż edytowanie na poziomie elementu działa dobrze w przypadku danych, które są aktualizowane tylko od czasu do czasu, niektóre scenariusze przypadków użycia wymagają od użytkownika edytowania wielu rekordów. Jeśli użytkownik musi edytować dziesiątki rekordów i musi kliknąć przycisk Edytuj, wprowadzić zmiany i kliknąć przycisk Aktualizuj dla każdego z nich, ilość kliknięć może utrudnić jej produktywność. W takich sytuacjach lepszym rozwiązaniem jest udostępnienie w pełni edytowalnej listy DataList, w której wszystkie jego elementy są w trybie edycji i których wartości można edytować, klikając przycisk Aktualizuj wszystko na stronie (zobacz Rysunek 1).
Rysunek 1. Każdy element w w pełni edytowalnej listy danych można zmodyfikować (kliknij, aby wyświetlić obraz pełnowymiarowy)
W tym samouczku sprawdzimy, jak umożliwić użytkownikom aktualizowanie informacji o adresach dostawców przy użyciu w pełni edytowalnej listy DataList.
Krok 1. Tworzenie edytowalnego interfejsu użytkownika w elemencie ItemTemplate elementu DataList
W poprzednim samouczku, w którym utworzyliśmy standardową, edytowalną listę danych na poziomie elementu, użyliśmy dwóch szablonów:
ItemTemplate
zawierał interfejs użytkownika tylko do odczytu (kontrolki Etykieta sieci Web służące do wyświetlania nazwy i ceny poszczególnych produktów).EditItemTemplate
zawierał interfejs użytkownika trybu edycji (dwa kontrolki sieci Web TextBox).
Właściwość DataList EditItemIndex
określa, co DataListItem
(jeśli istnieje) jest renderowane przy użyciu elementu EditItemTemplate
. W szczególności wartość, DataListItem
której ItemIndex
wartość jest zgodna z właściwością DataList, EditItemIndex
jest renderowana przy użyciu .EditItemTemplate
Ten model działa dobrze, gdy tylko jeden element można edytować naraz, ale rozpada się podczas tworzenia w pełni edytowalnej listy danych.
W przypadku w pełni edytowalnej listy DataList chcemy , aby wszystkie DataListItem
s renderowane przy użyciu interfejsu edytowalnego. Najprostszym sposobem osiągnięcia tego celu jest zdefiniowanie edytowalnego interfejsu w pliku ItemTemplate
. Aby zmodyfikować informacje o adresach dostawców, edytowalny interfejs zawiera nazwę dostawcy jako tekst, a następnie Pola tekstowe dla wartości adresu, miasta i kraju/regionu.
Zacznij od otwarcia strony, dodania kontrolki BatchUpdate.aspx
DataList i ustawienia jej ID
właściwości na Suppliers
. Z tagu inteligentnego DataList wybierz opcję dodania nowej kontrolki ObjectDataSource o nazwie SuppliersDataSource
.
Rysunek 2. Tworzenie nowego obiektuDataSource o nazwie SuppliersDataSource
(kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Skonfiguruj obiekt ObjectDataSource, aby pobrać dane przy użyciu SuppliersBLL
metody klasy s GetSuppliers()
(zobacz Rysunek 3). Podobnie jak w przypadku poprzedniego samouczka, zamiast aktualizować informacje o dostawcy za pośrednictwem obiektu ObjectDataSource, będziemy pracować bezpośrednio z warstwą logiki biznesowej. W związku z tym ustaw listę rozwijaną na wartość (Brak) na karcie UPDATE (zobacz Rysunek 4).
Rysunek 3. Pobieranie informacji o dostawcy przy użyciu GetSuppliers()
metody (kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 4. Ustaw listę rozwijaną na (Brak) na karcie AKTUALIZACJA (kliknij, aby wyświetlić obraz pełnowymiarowy)
Po ukończeniu pracy kreatora program Visual Studio automatycznie wygeneruje listę danych, ItemTemplate
aby wyświetlić każde pole danych zwrócone przez źródło danych w kontrolce Etykieta w sieci Web. Musimy zmodyfikować ten szablon, aby zamiast tego udostępniał interfejs edycji. Element ItemTemplate
można dostosować za pomocą projektanta przy użyciu opcji Edytuj szablony z tagu inteligentnego DataList lub bezpośrednio za pomocą składni deklaratywnej.
Pośmiń chwilę na utworzenie interfejsu edycji, który wyświetla nazwę dostawcy jako tekst, ale zawiera pola TextBoxes dla wartości adresu dostawcy, miasta i kraju/regionu. Po wprowadzeniu tych zmian składnia deklaratywna strony powinna wyglądać podobnie do następującej:
<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>
Uwaga
Podobnie jak w przypadku poprzedniego samouczka, lista DataList w tym samouczku musi mieć włączony stan widoku.
W narzędziu ItemTemplate
używam dwóch nowych klas SupplierPropertyLabel
CSS i SupplierPropertyValue
, które zostały dodane do Styles.css
klasy i skonfigurowane do używania tych samych ustawień stylu co ProductPropertyLabel
klasy i ProductPropertyValue
CSS.
.ProductPropertyLabel, .SupplierPropertyLabel
{
font-weight: bold;
text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
padding-right: 35px;
}
Po wprowadzeniu tych zmian odwiedź tę stronę za pośrednictwem przeglądarki. Jak pokazano na rysunku 5, każdy element DataList wyświetla nazwę dostawcy jako tekst i używa pola TextBoxes do wyświetlania adresu, miasta i kraju/regionu.
Rysunek 5. Każdy dostawca w liście DataList jest edytowalny (kliknij, aby wyświetlić obraz o pełnym rozmiarze)
Krok 2. Dodawanie przycisku Aktualizuj wszystko
Chociaż każdy dostawca na rysunku 5 ma swoje pola adresowe, miasto i kraj/region wyświetlane w polu tekstowym, obecnie nie ma dostępnego przycisku Aktualizuj. Zamiast mieć przycisk Aktualizuj dla każdego elementu, z w pełni edytowalnymi elementami DataLists na stronie jest zwykle jeden przycisk Aktualizuj wszystko, który po kliknięciu aktualizuje wszystkie rekordy w liście DataList. W tym samouczku dodajmy dwa przyciski Aktualizuj wszystkie — jeden w górnej części strony i jeden na dole (chociaż kliknięcie jednego przycisku będzie miało taki sam efekt).
Zacznij od dodania kontrolki Sieć Web przycisku powyżej kontrolki DataList i ustaw jej ID
właściwość na UpdateAll1
. Następnie dodaj drugą kontrolkę Sieć Web przycisku poniżej kontrolki DataList, ustawiając jej ID
wartość na UpdateAll2
. Text
Ustaw właściwości dla dwóch przycisków na Aktualizuj wszystko. Na koniec utwórz programy obsługi zdarzeń dla obu zdarzeń Przycisków Click
. Zamiast duplikować logikę aktualizacji w każdym z programów obsługi zdarzeń, refaktoryzujmy tę logikę do trzeciej metody , UpdateAllSupplierAddresses
dzięki czemu procedury obsługi zdarzeń po prostu wywołają tę trzecią metodę.
Protected Sub UpdateAll1_Click(sender As Object, e As EventArgs) _
Handles UpdateAll1.Click
UpdateAllSupplierAddresses()
End Sub
Protected Sub UpdateAll2_Click(sender As Object, e As EventArgs) _
Handles UpdateAll2.Click
UpdateAllSupplierAddresses()
End Sub
Private Sub UpdateAllSupplierAddresses()
' TODO: Write code to update _all_ of the supplier addresses in the DataList
End Sub
Rysunek 6 przedstawia stronę po dodaniu przycisków Aktualizuj wszystkie.
Rysunek 6. Dodano dwa przyciski Aktualizuj wszystkie do strony (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 3. Aktualizowanie wszystkich informacji o adresach dostawców
W przypadku wszystkich elementów elementu DataList wyświetlających interfejs edycji i dodawania przycisków Aktualizuj wszystkie pozostaje napisanie kodu w celu przeprowadzenia aktualizacji wsadowej. W szczególności musimy przeprowadzić pętlę przez elementy elementu DataList i wywołać metodę SuppliersBLL
s UpdateSupplierAddress
klasy dla każdego z nich.
Kolekcja DataListItem
wystąpień, do których można uzyskać dostęp za pośrednictwem właściwości DataListItems
. Przy użyciu odwołania do elementu DataListItem
możemy pobrać odpowiedni SupplierID
element z DataKeys
kolekcji i programowo odwołać się do kontrolek sieci Web TextBox w ItemTemplate
programie , jak pokazano w poniższym kodzie:
Private Sub UpdateAllSupplierAddresses()
' Create an instance of the SuppliersBLL class
Dim suppliersAPI As New SuppliersBLL()
' Iterate through the DataList's items
For Each item As DataListItem In Suppliers.Items
' Get the supplierID from the DataKeys collection
Dim supplierID As Integer = Convert.ToInt32(Suppliers.DataKeys(item.ItemIndex))
' Read in the user-entered values
Dim address As TextBox = CType(item.FindControl("Address"), TextBox)
Dim city As TextBox = CType(item.FindControl("City"), TextBox)
Dim country As TextBox = CType(item.FindControl("Country"), TextBox)
Dim addressValue As String = Nothing, _
cityValue As String = Nothing, _
countryValue As String = Nothing
If address.Text.Trim().Length > 0 Then
addressValue = address.Text.Trim()
End If
If city.Text.Trim().Length > 0 Then
cityValue = city.Text.Trim()
End If
If country.Text.Trim().Length > 0 Then
countryValue = country.Text.Trim()
End If
' Call the SuppliersBLL class's UpdateSupplierAddress method
suppliersAPI.UpdateSupplierAddress _
(supplierID, addressValue, cityValue, countryValue)
Next
End Sub
Gdy użytkownik kliknie jeden z przycisków Aktualizuj wszystkie, UpdateAllSupplierAddresses
metoda wykonuje iterację po każdej DataListItem
z nich w metodzie Suppliers
DataList i wywołuje SuppliersBLL
metodę s UpdateSupplierAddress
klasy, przekazując odpowiednie wartości. Niewprowadzona wartość dla adresu, miasta lub kraju/regionu jest wartością Nothing
do UpdateSupplierAddress
(zamiast pustego ciągu), która powoduje, że baza danych NULL
dla pól rekordu bazowego.
Uwaga
W ramach ulepszenia możesz dodać kontrolkę Etykieta stanu w sieci Web do strony zawierającej komunikat potwierdzający po wykonaniu aktualizacji wsadowej.
Aktualizowanie tylko tych adresów, które zostały zmodyfikowane
Algorytm aktualizacji wsadowej używany w tym samouczku wywołuje metodę UpdateSupplierAddress
dla każdego dostawcy w usłudze DataList, niezależnie od tego, czy informacje o adresach zostały zmienione. Chociaż takie ślepe aktualizacje nie są zwykle problemem z wydajnością, mogą prowadzić do nadmiarowych rekordów, jeśli przeprowadzasz inspekcję zmian w tabeli bazy danych. Jeśli na przykład używasz wyzwalaczy do rejestrowania wszystkich UPDATE
s Suppliers
w tabeli do tabeli inspekcji, za każdym razem, gdy użytkownik kliknie przycisk Aktualizuj wszystko, zostanie utworzony nowy rekord inspekcji dla każdego dostawcy w systemie, niezależnie od tego, czy użytkownik dokonał jakichkolwiek zmian.
Klasy ADO.NET DataTable i DataAdapter są przeznaczone do obsługi aktualizacji wsadowych, w których tylko zmodyfikowane, usunięte i nowe rekordy prowadzą do komunikacji z dowolną bazą danych. Każdy wiersz w tabeli DataTable ma właściwość wskazującąRowState
, czy wiersz został dodany do tabeli DataTable, usunięty z niej, zmodyfikowany lub pozostaje niezmieniony. Po początkowym wypełnieniu tabeli DataTable wszystkie wiersze są oznaczone bez zmian. Zmiana wartości dowolnej kolumny wierszy oznacza wiersz zgodnie z modyfikacją.
SuppliersBLL
W klasie aktualizujemy informacje o adresach określonego dostawcy, najpierw odczytując w rekordzie pojedynczego dostawcy do SuppliersDataTable
elementu , a następnie ustawiamy Address
wartości kolumn , City
i Country
przy użyciu następującego kodu:
Public Function UpdateSupplierAddress _
(supplierID As Integer, address As String, city As String, country As String) _
As Boolean
Dim suppliers As Northwind.SuppliersDataTable = _
Adapter.GetSupplierBySupplierID(supplierID)
If suppliers.Count = 0 Then
' no matching record found, return false
Return False
Else
Dim supplier As Northwind.SuppliersRow = suppliers(0)
If address Is Nothing Then
supplier.SetAddressNull()
Else
supplier.Address = address
End If
If city Is Nothing Then
supplier.SetCityNull()
Else
supplier.City = city
End If
If country Is Nothing Then
supplier.SetCountryNull()
Else
supplier.Country = country
End If
' Update the supplier Address-related information
Dim rowsAffected As Integer = Adapter.Update(supplier)
' Return true if precisely one row was updated, otherwise false
Return rowsAffected = 1
End If
End Function
Ten kod naiwnie przypisuje przekazane wartości adresu, miasta i kraju/regionu do SuppliersRow
elementu w SuppliersDataTable
niezależnie od tego, czy wartości zostały zmienione. Te modyfikacje powodują SuppliersRow
oznaczenie właściwości s RowState
jako zmodyfikowanej. Po wywołaniu metody warstwy Update
dostępu do danych zobaczysz, że SupplierRow
element został zmodyfikowany i w związku z UPDATE
tym wysyła polecenie do bazy danych.
Załóżmy jednak, że dodaliśmy kod do tej metody w celu przypisania tylko przekazanych wartości adresu, miasta i kraju/regionu, jeśli różnią się one od SuppliersRow
istniejących wartości. W przypadku, gdy adres, miasto i kraj/region są takie same jak istniejące dane, nie zostaną wprowadzone żadne zmiany, a SupplierRow
znaki s RowState
zostaną oznaczone jako niezmienione. Wynikiem net jest to, że po wywołaniu metody DAL Update
nie zostanie wykonane żadne wywołanie bazy danych, ponieważ SuppliersRow
nie został zmodyfikowany.
Aby wprowadzić tę zmianę, zastąp instrukcje, które ślepo przypisują przekazany adres, miasto i wartości kraju/regionu następującym kodem:
' Only assign the values to the SupplierRow's column values if they differ
If address Is Nothing AndAlso Not supplier.IsAddressNull() Then
supplier.SetAddressNull()
ElseIf (address IsNot Nothing AndAlso supplier.IsAddressNull) _
OrElse (Not supplier.IsAddressNull() AndAlso _
String.Compare(supplier.Address, address) <> 0) Then
supplier.Address = address
End If
If city Is Nothing AndAlso Not supplier.IsCityNull() Then
supplier.SetCityNull()
ElseIf (city IsNot Nothing AndAlso supplier.IsCityNull) _
OrElse (Not supplier.IsCityNull() AndAlso _
String.Compare(supplier.City, city) <> 0) Then
supplier.City = city
End If
If country Is Nothing AndAlso Not supplier.IsCountryNull() Then
supplier.SetCountryNull()
ElseIf (country IsNot Nothing AndAlso supplier.IsCountryNull) _
OrElse (Not supplier.IsCountryNull() AndAlso _
String.Compare(supplier.Country, country) <> 0) Then
supplier.Country = country
End If
W przypadku tego dodanego kodu metoda DAL Update
wysyła instrukcję UPDATE
do bazy danych tylko dla tych rekordów, których wartości związane z adresami uległy zmianie.
Alternatywnie można śledzić, czy istnieją jakieś różnice między przekazanymi polami adresów a danymi bazy danych, a jeśli ich nie ma, po prostu pomiń wywołanie metody DAL Update
. Takie podejście sprawdza się dobrze, jeśli używasz metody bezpośredniej bazy danych, ponieważ metoda bezpośrednia bazy danych nie jest przekazywana SuppliersRow
do wystąpienia, którego RowState
można sprawdzić, czy wywołanie bazy danych jest rzeczywiście potrzebne.
Uwaga
Za każdym razem, gdy UpdateSupplierAddress
metoda jest wywoływana, do bazy danych jest wykonywane wywołanie w celu pobrania informacji o zaktualizowanym rekordzie. Następnie, jeśli istnieją jakiekolwiek zmiany w danych, zostanie wykonane kolejne wywołanie bazy danych w celu zaktualizowania wiersza tabeli. Ten przepływ pracy można zoptymalizować, tworząc UpdateSupplierAddress
przeciążenie metody, które akceptuje EmployeesDataTable
wystąpienie, które zawiera wszystkie zmiany ze BatchUpdate.aspx
strony. Następnie może wykonać jedno wywołanie bazy danych, aby pobrać wszystkie rekordy z Suppliers
tabeli. Następnie można wyliczyć dwa zestawy wyników i tylko te rekordy, w których wystąpiły zmiany.
Podsumowanie
W tym samouczku pokazano, jak utworzyć w pełni edytowalną listę DataList, umożliwiając użytkownikowi szybkie modyfikowanie informacji o adresie dla wielu dostawców. Zaczęliśmy od zdefiniowania interfejsu edycji kontrolki internetowej TextBox dla wartości adresu dostawcy, miasta i kraju/regionu w elemecie DataList s ItemTemplate
. Następnie dodaliśmy przyciski Aktualizuj wszystkie powyżej i poniżej pozycji DataList. Po wprowadzeniu zmian przez użytkownika i kliknięciu jednego z przycisków DataListItem
Aktualizuj wszystkie zostaną wyliczone znaki s i zostanie wykonane wywołanie SuppliersBLL
metody klasy UpdateSupplierAddress
.
Szczęśliwe programowanie!
Informacje o autorze
Scott Mitchell, autor siedmiu książek ASP/ASP.NET i założyciel 4GuysFromRolla.com, współpracuje z technologiami internetowymi firmy Microsoft od 1998 roku. Scott pracuje jako niezależny konsultant, trener i pisarz. Jego najnowsza książka to Sams Teach Yourself ASP.NET 2.0 w 24 godzinach. Można go uzyskać pod adresem mitchell@4GuysFromRolla.com. lub za pośrednictwem swojego bloga, który można znaleźć na stronie http://ScottOnWriting.NET.
Specjalne podziękowania
Ta seria samouczków została omówiona przez wielu przydatnych recenzentów. Recenzenci z tego samouczka to Zack Jones i Ken Pespisa. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.