Udostępnij za pośrednictwem


Aktualizowanie w partiach (VB)

Autor: Scott Mitchell

Pobierz plik PDF

Dowiedz się, jak zaktualizować wiele rekordów bazy danych w ramach jednej operacji. W warstwie interfejsu użytkownika tworzymy obiekt GridView, w którym każdy wiersz można edytować. W warstwie dostępu do danych opakowujemy wiele operacji aktualizacji w ramach transakcji, aby upewnić się, że wszystkie aktualizacje zostaną wycofane lub wszystkie aktualizacje.

Wprowadzenie

W poprzednim samouczku pokazano, jak rozszerzyć warstwę dostępu do danych w celu dodania obsługi transakcji bazy danych. Transakcje bazy danych gwarantują, że seria instrukcji modyfikacji danych będzie traktowana jako jedna operacja niepodzielna, co gwarantuje, że wszystkie modyfikacje nie powiedzą się lub wszystkie zostaną wykonane pomyślnie. Dzięki tej funkcji dal niskiego poziomu jesteśmy gotowi zwrócić uwagę na tworzenie interfejsów modyfikacji danych wsadowych.

W tym samouczku utworzymy obiekt GridView, w którym można edytować każdy wiersz (zobacz Rysunek 1). Ponieważ każdy wiersz jest renderowany w interfejsie edycji, nie ma potrzeby tworzenia kolumn przycisków Edytuj, Aktualizuj i Anuluj. Zamiast tego na stronie znajdują się dwa przyciski Aktualizuj produkty, które po kliknięciu wyliczają wiersze GridView i aktualizują bazę danych.

Każdy wiersz w siatceView jest edytowalny

Rysunek 1. Każdy wiersz w widoku GridView jest edytowalny (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Zacznijmy!

Uwaga

W samouczku Wykonywanie aktualizacji usługi Batch utworzyliśmy interfejs edycji wsadowej przy użyciu kontrolki DataList. Ten samouczek różni się od poprzedniego w tym, który używa kontrolki GridView, a aktualizacja wsadowa jest wykonywana w zakresie transakcji. Po ukończeniu tego samouczka zachęcam do powrotu do wcześniejszego samouczka i zaktualizowania go do korzystania z funkcji związanych z transakcjami bazy danych dodanych w poprzednim samouczku.

Badanie kroków edytowania wszystkich wierszy kontrolki GridView

Zgodnie z opisem w samouczku Omówienie wstawiania, aktualizowania i usuwania danych funkcja GridView oferuje wbudowaną obsługę edytowania danych bazowych na podstawie wiersza. Wewnętrznie kontrolka GridView zauważa, jaki wiersz można edytować za pomocą jego EditIndex właściwości. Ponieważ element GridView jest powiązany ze źródłem danych, sprawdza każdy wiersz, aby sprawdzić, czy indeks wiersza jest równy wartości EditIndex. Jeśli tak, pola wierszy są renderowane przy użyciu interfejsów edycji. W przypadku obiektów BoundFields interfejs edycji to TextBox, którego Text właściwość ma przypisaną wartość pola danych określonego przez właściwość BoundField.DataField W przypadku obiektów TemplateFields EditItemTemplate element jest używany zamiast elementu ItemTemplate.

Pamiętaj, że edytowanie przepływu pracy rozpoczyna się, gdy użytkownik kliknie przycisk Edytuj wiersz. Powoduje to powrót, ustawia właściwość GridView EditIndex na indeks klikniętego wiersza i ponownie tworzy powiązanie danych z siatką. Po kliknięciu przycisku Anuluj wiersza po ponownym połączeniu danych z siatką zostanie ustawiona wartość -1 ogłaszania zwrotnegoEditIndex. Ponieważ wiersze kontrolki GridView zaczynają indeksować od zera, ustawienie EditIndex -1 ma wpływ na wyświetlanie kontrolki GridView w trybie tylko do odczytu.

Właściwość działa dobrze w przypadku edytowania EditIndex poszczególnych wierszy, ale nie jest przeznaczona do edycji wsadowej. Aby edytować cały element GridView, musimy mieć każdy wiersz renderowany przy użyciu interfejsu edycji. Najprostszym sposobem osiągnięcia tego celu jest utworzenie miejsca, w którym każde pole edytowalne jest implementowane jako pole szablonu z interfejsem edycji zdefiniowanym w pliku ItemTemplate.

W kolejnych kilku krokach utworzymy całkowicie edytowalny element GridView. W kroku 1 zaczniemy od utworzenia kontrolki GridView i jej obiektu ObjectDataSource oraz przekonwertowania pól BoundFields i CheckBoxField na pola szablonów. W krokach 2 i 3 przeniesiemy interfejsy edycji z pól szablonów EditItemTemplate do ich ItemTemplate elementów.

Krok 1. Wyświetlanie informacji o produkcie

Zanim zaczniemy martwić się o utworzenie kontrolki GridView, w której można edytować wiersze, zacznijmy od wyświetlenia informacji o produkcie. BatchUpdate.aspx Otwórz stronę w folderze BatchData i przeciągnij kontrolkę GridView z przybornika do projektanta. Ustaw właściwość GridView na ID ProductsGrid wartość i z tagu inteligentnego wybierz powiązanie go z nowym obiektem ObjectDataSource o nazwie ProductsDataSource. Skonfiguruj obiekt ObjectDataSource, aby pobrać dane z ProductsBLL metody klasy s GetProducts .

Konfigurowanie obiektu ObjectDataSource do używania klasy ProductsBLL

Rysunek 2. Konfigurowanie obiektu ObjectDataSource do używania ProductsBLL klasy (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Pobieranie danych produktu przy użyciu metody GetProducts

Rysunek 3. Pobieranie danych produktu przy użyciu GetProducts metody (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Podobnie jak w przypadku kontrolki GridView, funkcje modyfikacji obiektu ObjectDataSource są przeznaczone do pracy w poszczególnych wierszach. Aby zaktualizować zestaw rekordów, musimy napisać trochę kodu w klasie ASP.NET stronicowania kodu, która wsaduje dane i przekazuje je do usługi BLL. W związku z tym ustaw listy rozwijane na kartach ObjectDataSource s UPDATE, INSERT i DELETE na wartość (Brak). Kliknij przycisk Zakończ, aby zakończyć kreatora.

Ustaw listy rozwijane na kartach UPDATE, INSERT i DELETE na wartość (Brak)

Rysunek 4. Ustawianie list rozwijanych na kartach UPDATE, INSERT i DELETE na wartość (Brak) (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po ukończeniu pracy kreatora Konfigurowanie źródła danych znacznik deklaratywny objectDataSource powinien wyglądać następująco:

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

Ukończenie pracy Kreatora konfigurowania źródła danych powoduje również, że program Visual Studio tworzy pola BoundFields i CheckBoxField dla pól danych produktu w elementy GridView. W tym samouczku zezwólmy tylko użytkownikowi na wyświetlanie i edytowanie nazwy produktu, kategorii, ceny i stanu przerwania. Usuń wszystkie ProductNamepola , , CategoryNameUnitPrice, i i Discontinued zmień nazwy HeaderText właściwości pierwszych trzech pól odpowiednio na Product, Category i Price. Na koniec zaznacz pola wyboru Włącz stronicowanie i Włącz sortowanie w tagu inteligentnym GridView.

W tym momencie kontrolka GridView ma trzy pola boundfield (ProductName, CategoryNamei UnitPrice) i CheckBoxField (Discontinued). Musimy przekonwertować te cztery pola na pola szablonów, a następnie przenieść interfejs edycji z pola szablonu EditItemTemplate do elementu ItemTemplate.

Uwaga

Zapoznaliśmy się z tworzeniem i dostosowywaniem pól szablonów w samouczku Dostosowywanie interfejsu modyfikacji danych. Przejdziemy przez kroki konwertowania pól BoundFields i CheckBoxField na pola templatefields i definiowania ich interfejsów edycji w ItemTemplate ich s, ale jeśli utkniesz lub potrzebujesz odświeżenia, nie wahaj się odwołać się do tego wcześniejszego samouczka.

W tagu inteligentnym GridView kliknij link Edytuj kolumny, aby otworzyć okno dialogowe Pola. Następnie zaznacz każde pole i kliknij łącze Konwertuj to pole na pole szablonu.

Konwertowanie istniejących pól boundfields i CheckBoxField na pola szablonów

Rysunek 5. Konwertowanie istniejących pól granic i pola CheckBoxField na pola szablonów

Teraz, gdy każde pole jest polem TemplateField, możemy ponownie przenieść interfejs edycji z EditItemTemplate s do ItemTemplate s.

Krok 2. TworzenieProductNameUnitPrice iDiscontinuededytowanie interfejsów

ProductNameTworzenie interfejsów , UnitPricei Discontinued edycji jest tematem tego kroku i jest dość proste, ponieważ każdy interfejs jest już zdefiniowany w obszarze TemplateField sEditItemTemplate. Tworzenie interfejsu CategoryName edycji jest nieco bardziej zaangażowane, ponieważ musimy utworzyć listę rozwijaną odpowiednich kategorii. Ten CategoryName interfejs edycji jest rozwiązywany w kroku 3.

Zacznijmy od pola ProductName TemplateField. Kliknij link Edytuj szablony z tagu inteligentnego GridView i przejdź do szczegółów pola szablonu ProductName EditItemTemplate. Wybierz pozycję TextBox, skopiuj ją do schowka, a następnie wklej ją do pola ProductName templatefield s ItemTemplate. Zmień właściwość ProductNameTextBox na ID .

Następnie dodaj element RequiredFieldValidator do ItemTemplate elementu , aby upewnić się, że użytkownik podaje wartość dla każdej nazwy produktu. ControlToValidate Ustaw właściwość ProductName, ErrorMessage właściwość na Musisz podać nazwę produktu. Text i właściwość na *. Po dodaniu tych dodatków do ekranu powinien wyglądać podobnie do rysunku ItemTemplate6.

Pole szablonu ProductName zawiera teraz pole tekstowe i element RequiredFieldValidator

Rysunek 6. Pole ProductName szablonu zawiera teraz pole tekstowe i element RequiredFieldValidator (kliknij, aby wyświetlić obraz pełnowymiarowy)

W przypadku interfejsu UnitPrice edycji zacznij od skopiowania kontrolki TextBox z EditItemTemplate folderu ItemTemplatena . Następnie umieść wartość $ przed polem TextBox i ustaw jej właściwość na UnitPrice i jej ID Columns właściwość na 8 .

Dodaj również element CompareValidator do UnitPrice s ItemTemplate , aby upewnić się, że wartość wprowadzona przez użytkownika jest prawidłową wartością waluty większą lub równą 0,00 USD. Ustaw właściwość modułu sprawdzania ControlToValidate poprawności na UnitPrice, jej ErrorMessage właściwość na Wartość Musisz wprowadzić prawidłową wartość waluty. Pomiń wszelkie symbole waluty. Jej Text właściwość na *, jej Type właściwość na , jej Operator właściwość na CurrencyGreaterThanEqual, i jej ValueToCompare właściwość na 0 .

Dodaj moduł CompareValidator, aby upewnić się, że wprowadzona cena jest wartością nieujemną waluty

Rysunek 7. Dodawanie modułu CompareValidator w celu upewnienia się, że wprowadzona cena jest wartością waluty innej niż ujemna (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

W polu Discontinued TemplateField możesz użyć pola wyboru zdefiniowanego już w elem.ItemTemplate Po prostu ustaw wartość ID Na wartość Wycofano, a jej Enabled właściwość na Truewartość .

Krok 3. Tworzenie interfejsu edycjiCategoryName

Interfejs edycji w polach CategoryName TemplateField EditItemTemplate zawiera pole tekstowe, które wyświetla wartość CategoryName pola danych. Musimy zastąpić to listą rozwijaną, która zawiera listę możliwych kategorii.

Uwaga

Samouczek Dostosowywanie interfejsu modyfikacji danych zawiera bardziej szczegółową i kompletną dyskusję na temat dostosowywania szablonu w celu uwzględnienia listy rozwijanej w przeciwieństwie do kontrolki TextBox. Kroki opisane w tym miejscu są kompletne, ale są one prezentowane w sposób nietrwale. Aby uzyskać bardziej szczegółowe informacje na temat tworzenia i konfigurowania kategorii DropDownList, zapoznaj się z samouczkiem Dostosowywanie interfejsu modyfikacji danych.

Przeciągnij listę DropDownList z przybornika na CategoryName wartość TemplateField s ItemTemplate, ustawiając wartość ID Categories. Na tym etapie zwykle definiujemy źródło danych DropDownLists za pomocą tagu inteligentnego, tworząc nowy obiekt ObjectDataSource. Spowoduje to jednak dodanie obiektu ObjectDataSource w obiekcie ItemTemplate, co spowoduje utworzenie wystąpienia ObjectDataSource dla każdego wiersza kontrolki GridView. Zamiast tego utwórzmy obiekt ObjectDataSource poza polami TemplateFields kontrolki GridView. Zakończ edytowanie szablonu i przeciągnij element ObjectDataSource z przybornika do projektanta pod obiektem ProductsDataSource ObjectDataSource. Nadaj nowemu identyfikatorowi ObjectDataSource CategoriesDataSource nazwę i skonfiguruj ją tak, aby korzystała CategoriesBLL z metody klasy s GetCategories .

Konfigurowanie obiektu ObjectDataSource do używania klasy CategoriesBLL

Rysunek 8. Konfigurowanie obiektu ObjectDataSource do używania CategoriesBLL klasy (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Pobieranie danych kategorii przy użyciu metody GetCategories

Rysunek 9. Pobieranie danych kategorii przy użyciu GetCategories metody (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Ponieważ to źródło objectDataSource służy tylko do pobierania danych, ustaw listy rozwijane na kartach UPDATE i DELETE na wartość (Brak). Kliknij przycisk Zakończ, aby zakończyć kreatora.

Ustaw listy rozwijane na kartach UPDATE i DELETE na wartość (Brak)

Rysunek 10. Ustaw listy rozwijane na kartach UPDATE i DELETE na wartość (Brak) (Kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Po ukończeniu pracy kreatora CategoriesDataSource znacznik deklaratywny powinien wyglądać następująco:

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

Po utworzeniu i skonfigurowaniu CategoriesDataSource wróć do pola szablonu CategoryName ItemTemplate , a następnie z tagu inteligentnego DropDownList kliknij link Wybierz źródło danych. W kreatorze Konfiguracja źródła danych wybierz CategoriesDataSource opcję z pierwszej listy rozwijanej i wybierz opcję, która ma być CategoryName używana dla wyświetlania i CategoryID jako wartość.

Powiązywanie listy rozwijanej z kategoriamiDataSource

Rysunek 11. Powiązanie listy rozwijanej z listą CategoriesDataSource (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Na tym etapie lista Categories RozwijanaLista zawiera listę wszystkich kategorii, ale nie wybiera ona jeszcze automatycznie odpowiedniej kategorii dla produktu powiązanego z wierszem GridView. Aby to osiągnąć, musimy ustawić Categories wartość DropDownList s SelectedValue na CategoryID wartość produktu. Kliknij link Edytuj daneBindings z tagu inteligentnego DropDownList i skojarz SelectedValue właściwość z CategoryID polem danych, jak pokazano na rysunku 12.

Powiązanie wartości CategoryID produktu z właściwością SelectedValue listy rozwijanej

Rysunek 12. Powiązanie wartości produktu CategoryID z właściwością DropDownList SelectedValue

Pozostaje jeszcze jeden problem: jeśli produkt nie ma CategoryID określonej wartości, instrukcja powiązania danych na SelectedValue spowoduje wyjątek. Jest to spowodowane tym, że lista RozwijanaList zawiera tylko elementy kategorii i nie oferuje opcji dla tych produktów, które mają NULL wartość bazy danych dla CategoryIDelementu . Aby rozwiązać ten problem, ustaw właściwość DropDownList na AppendDataBoundItems True i dodaj nowy element do listy DropDownList, pomijając Value właściwość ze składni deklaratywnej. Oznacza to, że Categories składnia deklaratywna listy DropDownList wygląda następująco:

<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>

Zwróć uwagę, <asp:ListItem Value=""> jak parametr -- Select One -- (Wybierz jeden) ma jawnie Value ustawiony atrybut na pusty ciąg. Zapoznaj się z samouczkiem Dostosowywanie interfejsu modyfikacji danych, aby uzyskać bardziej szczegółową dyskusję na temat tego, dlaczego ten dodatkowy element DropDownList jest potrzebny do obsługi NULL sprawy i dlaczego przypisanie Value właściwości do pustego ciągu jest niezbędne.

Uwaga

Istnieje tu potencjalny problem z wydajnością i skalowalnością, który warto wspomnieć. Ponieważ każdy wiersz zawiera listę DropDownList, która używa CategoriesDataSource jako źródła danych, CategoriesBLL metoda s GetCategories klasy będzie wywoływana n razy na wizytę strony, gdzie n to liczba wierszy w kodzie GridView. Te n wywołania powodują, że GetCategories n zapytań do bazy danych. Ten wpływ na bazę danych można zmniejszyć przez buforowanie zwróconych kategorii w pamięci podręcznej poszczególnych żądań lub za pośrednictwem warstwy buforowania przy użyciu zależności buforowania SQL lub bardzo krótkiego wygaśnięcia na podstawie czasu.

Krok 4. Kończenie pracy z interfejsem edycji

Wprowadziliśmy wiele zmian w szablonach GridView bez wstrzymania w celu wyświetlenia postępu. Pośmiń chwilę, aby wyświetlić postęp w przeglądarce. Jak pokazano na rysunku 13, każdy wiersz jest renderowany przy użyciu elementu ItemTemplate, który zawiera interfejs edytowania komórek.

Każdy wiersz GridView jest edytowalny

Rysunek 13. Każdy wiersz kontrolki GridView można edytować (kliknij, aby wyświetlić obraz o pełnym rozmiarze)

Istnieje kilka drobnych problemów z formatowaniem, które należy wziąć pod uwagę w tym momencie. Najpierw należy pamiętać, że UnitPrice wartość zawiera cztery punkty dziesiętne. Aby rozwiązać ten problem, wróć do elementu UnitPrice TemplateField s ItemTemplate i z poziomu tagu inteligentnego TextBox kliknij link Edytuj elementy DataBindings. Następnie określ, że Text właściwość powinna być sformatowana jako liczba.

Formatowanie właściwości Text jako liczby

Rysunek 14. Formatowanie Text właściwości jako liczby

Po drugie wyśrodkujmy pole wyboru w kolumnie Discontinued (zamiast wyrównać ją do lewej). Kliknij pozycję Edytuj kolumny z tagu inteligentnego GridView i wybierz pozycję Discontinued TemplateField z listy pól w lewym dolnym rogu. Przejdź do ItemStyle szczegółów i ustaw właściwość na Center, jak pokazano na rysunku HorizontalAlign 15.

Wyśrodkowanie przerwanej skrzynki kontrolnej

Rysunek 15. Wyśrodkowanie Discontinued pola wyboru

Następnie dodaj kontrolkę ValidationSummary do strony i ustaw jej ShowMessageBox właściwość na True i jej ShowSummary właściwość na False. Dodaj również kontrolki Sieci Web przycisku, które po kliknięciu spowodują zaktualizowanie zmian użytkownika. W szczególności dodaj dwie kontrolki sieci Web przycisku, jedną powyżej kontrolki GridView i jedną poniżej, ustawiając obie właściwości kontrolek Text na Update Products .

Ponieważ interfejs edycji kontrolki GridView jest zdefiniowany w obszarze TemplateFields ItemTemplate , EditItemTemplate elementy te są zbędne i mogą zostać usunięte.

Po wprowadzeniu powyższych zmian formatowania, dodaniu kontrolek Przycisk i usunięciu niepotrzebnych EditItemTemplate elementów składni deklaratywnej strony powinna wyglądać następująco:

<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>

Rysunek 16 przedstawia tę stronę po wyświetleniu za pośrednictwem przeglądarki po dodaniu kontrolek Sieci Web przycisku i wprowadzeniu zmian formatowania.

Strona zawiera teraz dwa przyciski Aktualizuj produkty

Rysunek 16. Strona zawiera teraz dwa przyciski Aktualizuj produkty (kliknij, aby wyświetlić obraz pełnowymiarowy)

Krok 5. Aktualizowanie produktów

Gdy użytkownik odwiedzi tę stronę, wprowadzi modyfikacje, a następnie kliknij jeden z dwóch przycisków Aktualizuj produkty. W tym momencie musimy w jakiś sposób zapisać wartości wprowadzone przez użytkownika dla każdego wiersza w ProductsDataTable wystąpieniu, a następnie przekazać je do metody BLL, która następnie przekaże to ProductsDataTable wystąpienie do metody DAL.UpdateWithTransaction Metoda, która została utworzona UpdateWithTransaction w poprzednim samouczku, gwarantuje, że partia zmian zostanie zaktualizowana jako operacja niepodzielna.

Utwórz metodę o nazwie BatchUpdate w pliku BatchUpdate.aspx.vb i dodaj następujący kod:

Private Sub BatchUpdate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As Northwind.ProductsDataTable = productsAPI.GetProducts()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Find the ProductsRow instance in products that maps to gvRow
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim product As Northwind.ProductsRow = products.FindByProductID(productID)
        If product IsNot Nothing Then
            ' Programmatically access the form field elements in the 
            ' current GridViewRow
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateWithTransaction(products)
End Sub

Ta metoda rozpoczyna się od pobrania wszystkich produktów z powrotem do ProductsDataTable metody BLL za pośrednictwem wywołania metody BLL GetProducts . Następnie wylicza ProductGrid kolekcję GridViewRows. Kolekcja Rows zawiera GridViewRow wystąpienie dla każdego wiersza wyświetlanego w elementy GridView. Ponieważ pokazujemy co najwyżej dziesięć wierszy na stronę, kolekcja GridView Rows nie będzie zawierać więcej niż dziesięciu elementów.

Dla każdego wiersza element ProductID jest pobierany z DataKeys kolekcji, a odpowiedni ProductsRow element jest wybierany z elementu ProductsDataTable. Cztery kontrolki wejściowe TemplateField są programowo przywołyane i ich wartości przypisane do ProductsRow właściwości wystąpienia. Po zaktualizowaniu wartości ProductsDataTablewiersza kontrolki GridView jest przekazywana do metody BLL UpdateWithTransaction , która, jak pokazano w poprzednim samouczku, po prostu wywołuje metodę DAL UpdateWithTransaction .

Algorytm aktualizacji wsadowej używany na potrzeby tego samouczka aktualizuje każdy wiersz w ProductsDataTable elemecie GridView, niezależnie od tego, czy informacje o produkcie 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. W samouczku Dotyczącym wykonywania aktualizacji usługi Batch zapoznaliśmy się z interfejsem aktualizacji wsadowej za pomocą elementu DataList i dodaliśmy kod, który zaktualizowałby tylko te rekordy, które zostały rzeczywiście zmodyfikowane przez użytkownika. W razie potrzeby możesz użyć technik z sekcji Wykonywanie aktualizacji usługi Batch w celu zaktualizowania kodu w tym samouczku.

Uwaga

Po powiązaniu źródła danych z kontrolką GridView za pomocą tagu inteligentnego program Visual Studio automatycznie przypisuje wartości klucza podstawowego źródła danych do właściwości GridView DataKeyNames . Jeśli element ObjectDataSource nie został powiązany z kontrolką GridView za pomocą tagu inteligentnego GridView zgodnie z opisem w kroku 1, należy ręcznie ustawić właściwość GridView DataKeyNames na Wartość ProductID, aby uzyskać dostęp do ProductID wartości dla każdego wiersza za pośrednictwem DataKeys kolekcji.

Kod używany w systemie BatchUpdate jest podobny do tego, który jest używany w metodach BLL UpdateProduct , główną różnicą jest to, że w UpdateProduct metodach pobiera się tylko jedno ProductRow wystąpienie z architektury. Kod, który przypisuje właściwości obiektu ProductRow , jest taki sam między metodami UpdateProducts a kodem w For Each pętli w BatchUpdateelemecie , co jest ogólnym wzorcem.

Aby ukończyć ten samouczek, musimy wywołać metodę BatchUpdate po kliknięciu jednego z przycisków Aktualizuj produkty. Utwórz programy obsługi zdarzeń dla Click zdarzeń tych dwóch kontrolek przycisków i dodaj następujący kod w programach obsługi zdarzeń:

BatchUpdate()
ClientScript.RegisterStartupScript(Me.GetType(), "message", _
    "alert('The products have been updated.');", True)

Najpierw wykonano połączenie do BatchUpdate. Następnie właściwość jest używana do wstrzykiwania kodu JavaScript, ClientScript który wyświetli pole komunikatu z informacją o zaktualizowaniu produktów.

Pośmiń minutę na przetestowanie tego kodu. Odwiedź BatchUpdate.aspx przeglądarkę, edytuj kilka wierszy i kliknij jeden z przycisków Aktualizuj produkty. Przy założeniu, że nie ma żadnych błędów walidacji danych wejściowych, powinien zostać wyświetlony komunikat z informacją o zaktualizowaniu produktów. Aby sprawdzić niepodzielność aktualizacji, rozważ dodanie losowego CHECK ograniczenia, na przykład takiego, który nie zezwala UnitPrice na wartości 1234.56. Następnie z BatchUpdate.aspxpliku zmodyfikuj liczbę rekordów, upewniając się, że ustawiono jedną z wartości produktu UnitPrice na wartość zabronione (1234.56 ). Powinno to spowodować błąd podczas klikania pozycji Aktualizuj produkty z innymi zmianami podczas tej operacji wsadowej wycofanej do oryginalnych wartości.

Metoda alternatywnaBatchUpdate

Metoda BatchUpdate , którą właśnie zbadaliśmy, pobiera wszystkie produkty z metody BLL, GetProducts a następnie aktualizuje tylko te rekordy, które są wyświetlane w kontrolce GridView. Takie podejście jest idealne, jeśli element GridView nie używa stronicowania, ale jeśli tak, może istnieć setki, tysiące lub dziesiątki tysięcy produktów, ale tylko dziesięć wierszy w siatce. W takim przypadku pobranie wszystkich produktów z bazy danych tylko do zmodyfikowania 10 z nich jest mniejsze niż idealne.

W przypadku tych typów sytuacji rozważ użycie następującej BatchUpdateAlternate metody:

Private Sub BatchUpdateAlternate()
    ' Enumerate the GridView's Rows collection and create a ProductRow
    Dim productsAPI As New ProductsBLL()
    Dim products As New Northwind.ProductsDataTable()
    For Each gvRow As GridViewRow In ProductsGrid.Rows
        ' Create a new ProductRow instance
        Dim productID As Integer = _
            Convert.ToInt32(ProductsGrid.DataKeys(gvRow.RowIndex).Value)
        Dim currentProductDataTable As Northwind.ProductsDataTable = _
            productsAPI.GetProductByProductID(productID)
        If currentProductDataTable.Rows.Count > 0 Then
            Dim product As Northwind.ProductsRow = currentProductDataTable(0)
            Dim productName As TextBox = _
                CType(gvRow.FindControl("ProductName"), TextBox)
            Dim categories As DropDownList = _
                CType(gvRow.FindControl("Categories"), DropDownList)
            Dim unitPrice As TextBox = _
                CType(gvRow.FindControl("UnitPrice"), TextBox)
            Dim discontinued As CheckBox = _
                CType(gvRow.FindControl("Discontinued"), CheckBox)
            ' Assign the user-entered values to the current ProductRow
            product.ProductName = productName.Text.Trim()
            If categories.SelectedIndex = 0 Then 
                product.SetCategoryIDNull() 
            Else 
                product.CategoryID = Convert.ToInt32(categories.SelectedValue)
            End If
            If unitPrice.Text.Trim().Length = 0 Then 
                product.SetUnitPriceNull() 
            Else 
                product.UnitPrice = Convert.ToDecimal(unitPrice.Text)
            End If
            product.Discontinued = discontinued.Checked
            ' Import the ProductRow into the products DataTable
            products.ImportRow(product)
        End If
    Next
    ' Now have the BLL update the products data using a transaction
    productsAPI.UpdateProductsWithTransaction(products)
End Sub

BatchMethodAlternate rozpoczyna się od utworzenia nowego pustego ProductsDataTable o nazwie products. Następnie przechodzi przez kolekcję GridView Rows i dla każdego wiersza pobiera określone informacje o produkcie przy użyciu metody BLL.GetProductByProductID(productID) Pobrane ProductsRow wystąpienie ma właściwości zaktualizowane w taki sam sposób jak BatchUpdate, ale po zaktualizowaniu wiersza jest importowany do products ProductsDataTable obiektu za pomocą metody DataTableImportRow(DataRow).

Po zakończeniu For Each products pętli zawiera jedno ProductsRow wystąpienie dla każdego wiersza w pętli GridView. Od czasu dodania każdego ProductsRow wystąpienia do products elementu (zamiast aktualizacji), jeśli ślepo przekażemy je do UpdateWithTransaction metody , ProductsTableAdapter metoda spróbuje wstawić każdy rekord do bazy danych. Zamiast tego musimy określić, że każdy z tych wierszy został zmodyfikowany (nie został dodany).

Można to osiągnąć, dodając nową metodę do BLL o nazwie UpdateProductsWithTransaction. UpdateProductsWithTransaction, jak pokazano poniżej, ustawia RowState każdą z ProductsRow wystąpień w ProductsDataTable obiekcie na Modified , a następnie przekazuje element ProductsDataTable do metody DAL.UpdateWithTransaction

Public Function UpdateProductsWithTransaction _
    (ByVal products As Northwind.ProductsDataTable) As Integer
    ' Mark each product as Modified
    products.AcceptChanges()
    For Each product As Northwind.ProductsRow In products
        product.SetModified()
    Next
    ' Update the data via a transaction
    Return UpdateWithTransaction(products)
End Function

Podsumowanie

Funkcja GridView zapewnia wbudowane funkcje edytowania wierszy, ale nie obsługuje tworzenia w pełni edytowalnych interfejsów. Jak pokazano w tym samouczku, takie interfejsy są możliwe, ale wymagają trochę pracy. Aby utworzyć obiekt GridView, w którym można edytować każdy wiersz, musimy przekonwertować pola kontrolki GridView na pola TemplateFields i zdefiniować interfejs edycji w s ItemTemplate . Ponadto do strony należy dodać kontrolki Sieci Web Aktualizuj wszystko -type, niezależnie od kontrolki GridView. Te programy obsługi zdarzeń przycisków Click muszą wyliczyć kolekcję GridView Rows , zapisać zmiany w ProductsDataTableobiekcie i przekazać zaktualizowane informacje do odpowiedniej metody BLL.

W następnym samouczku zobaczymy, jak utworzyć interfejs do usuwania wsadowego. W szczególności każdy wiersz Kontrolka GridView będzie zawierać pole wyboru, a zamiast przycisków Aktualizuj wszystkie -type, będziemy mieli przyciski Usuń zaznaczone wiersze.

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 w tym samouczku to Teresa Murphy i David Suru. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.