Wstawianie w partiach (VB)
Dowiedz się, jak wstawić wiele rekordów bazy danych w jednej operacji. W warstwie interfejsu użytkownika rozszerzymy kontrolkę GridView, aby umożliwić użytkownikowi wprowadzanie wielu nowych rekordów. W warstwie dostępu do danych opakowujemy wiele operacji wstawiania w ramach transakcji, aby upewnić się, że wszystkie operacje wstawiania kończą się powodzeniem lub wszystkie operacje wstawiania zostaną wycofane.
Wprowadzenie
W samouczku dotyczącym aktualizacji usługi Batch przyjrzeliśmy się dostosowywaniu kontrolki GridView w celu przedstawienia interfejsu, w którym można edytować wiele rekordów. Użytkownik odwiedzający stronę może wprowadzić serię zmian, a następnie, za pomocą jednego przycisku, przeprowadzić aktualizację wsadową. W sytuacjach, w których użytkownicy często aktualizują wiele rekordów w jednym miejscu, taki interfejs może zapisywać niezliczone kliknięcia i przełączniki kontekstowe klawiatury do myszy w porównaniu z domyślnymi funkcjami edycji poszczególnych wierszy, które zostały po raz pierwszy zbadane w samouczku Omówienie wstawiania , aktualizowania i usuwania danych .
Tę koncepcję można również zastosować podczas dodawania rekordów. Załóżmy, że w firmie Northwind Traders często otrzymujemy przesyłki od dostawców, którzy zawierają wiele produktów dla określonej kategorii. Na przykład możemy otrzymać przesyłkę sześciu różnych produktów herbacianych i kawy od Firmy Tokio Traders. Jeśli użytkownik wprowadzi sześć produktów pojedynczo za pomocą kontrolki DetailsView, będzie musiał wybrać wiele tych samych wartości po raz kolejny: będzie musiał wybrać tę samą kategorię (Napoje), tego samego dostawcę (Tokio Traders), tę samą wartość przerwaną (Fałsz) i te same jednostki w wartości zamówienia (0). Ten powtarzalny wpis danych jest nie tylko czasochłonny, ale jest podatny na błędy.
Przy odrobinie pracy możemy utworzyć interfejs wstawiania wsadowego, który umożliwia użytkownikowi wybranie dostawcy i kategorii raz, wprowadzenie serii nazw produktów i cen jednostkowych, a następnie kliknięcie przycisku, aby dodać nowe produkty do bazy danych (zobacz Rysunek 1). Po dodaniu każdego produktu pola danych ProductName
i UnitPrice
są przypisywane wartości wprowadzone w polach TextBoxes, podczas gdy jej CategoryID
wartości i SupplierID
są przypisywane wartości z listy DropDownLists u góry formularza. Wartości Discontinued
i UnitsOnOrder
są ustawione odpowiednio na wartości zakodowane False
na twardo i 0.
Rysunek 1. Interfejs wstawiania wsadowego (kliknij, aby wyświetlić obraz pełnowymiarowy)
W tym samouczku utworzymy stronę, która implementuje interfejs wstawiania wsadowego pokazany na rysunku 1. Podobnie jak w przypadku poprzednich dwóch samouczków, opakowujemy wstawiania w zakresie transakcji, aby zapewnić niepodzielność. Zacznijmy!
Krok 1. Tworzenie interfejsu wyświetlania
Ten samouczek składa się z jednej strony podzielonej na dwa regiony: region wyświetlania i region wstawiania. Interfejs wyświetlania, który utworzymy w tym kroku, pokazuje produkty w elemecie GridView i zawiera przycisk zatytułowany Przetwarzanie wysyłki produktu. Po kliknięciu tego przycisku interfejs wyświetlania jest zastępowany interfejsem wstawiania, który jest wyświetlany na rysunku 1. Interfejs wyświetlania jest zwracany po kliknięciu przycisków Dodaj produkty z przesyłki lub Anulowania. Utworzymy interfejs wstawiania w kroku 2.
Podczas tworzenia strony, która ma dwa interfejsy, tylko jeden z nich jest widoczny jednocześnie, każdy interfejs jest zwykle umieszczany w kontrolce Sieci Web Panelu, która służy jako kontener dla innych kontrolek. W związku z tym nasza strona będzie miała dwa kontrolki Panel jeden dla każdego interfejsu.
Zacznij od otwarcia BatchInsert.aspx
strony w BatchData
folderze i przeciągnij panel z przybornika do Projektant (patrz Rysunek 2). Ustaw właściwość Panel na ID
DisplayInterface
. Podczas dodawania panelu do Projektant jego Height
właściwości i Width
są ustawione odpowiednio na 50 pikseli i 125 pikseli. Wyczyść te wartości właściwości z okno Właściwości.
Rysunek 2. Przeciągnij panel z przybornika na Projektant (kliknij, aby wyświetlić obraz pełnowymiarowy)
Następnie przeciągnij kontrolkę Button i GridView do panelu. Ustaw właściwość Button ID
na ProcessShipment
i jej Text
właściwość na Process Product Shipment. Ustaw właściwość GridView ID
na ProductsGrid
i z jego tagu inteligentnego powiąż ją z nowym obiektem ObjectDataSource o nazwie ProductsDataSource
. Skonfiguruj obiekt ObjectDataSource, aby ściągnąć dane z ProductsBLL
metody klasy s GetProducts
. Ponieważ ten element GridView jest używany tylko do wyświetlania danych, ustaw listę rozwijaną na kartach UPDATE, INSERT i DELETE na wartość (Brak). Kliknij przycisk Zakończ, aby ukończyć pracę kreatora Konfigurowanie źródła danych.
Rysunek 3. Wyświetlanie danych zwróconych z ProductsBLL
metody klasy GetProducts
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 4. Ustawianie Drop-Down Listy na kartach UPDATE, INSERT i DELETE na wartość (Brak) (Kliknij, aby wyświetlić obraz pełnowymiarowy)
Po ukończeniu pracy kreatora ObjectDataSource program Visual Studio doda pola BoundFields i CheckBoxField dla pól danych produktu. Usuń wszystkie, ale ProductName
pola , CategoryName
, SupplierName
, UnitPrice
i Discontinued
. Możesz swobodnie wprowadzać wszelkie dostosowania estetyki. Postanowiłem sformatować UnitPrice
pole jako wartość waluty, zmienić kolejność pól i zmienić nazwę kilku wartości pól HeaderText
. Skonfiguruj również kontrolkę GridView tak, aby zawierała obsługę stronicowania i sortowania, zaznaczając pola wyboru Włącz stronicowanie i Włącz sortowanie w tagu inteligentnym GridView.
Po dodaniu kontrolek Panel, Button, GridView i ObjectDataSource oraz dostosowywaniu pól GridView znacznik deklaratywny strony powinien wyglądać podobnie do następującego:
<asp:Panel ID="DisplayInterface" runat="server">
<p>
<asp:Button ID="ProcessShipment" runat="server"
Text="Process Product Shipment" />
</p>
<asp:GridView ID="ProductsGrid" runat="server" AllowPaging="True"
AllowSorting="True" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="Supplier"
ReadOnly="True" SortExpression="SupplierName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price" HtmlEncode="False"
SortExpression="UnitPrice">
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued">
<ItemStyle HorizontalAlign="Center" />
</asp:CheckBoxField>
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
</asp:Panel>
Należy pamiętać, że znaczniki przycisku i kontrolki GridView są wyświetlane w tagach otwierania i zamykania <asp:Panel>
. Ponieważ te kontrolki znajdują się w DisplayInterface
panelu, możemy je ukryć, ustawiając właściwość Panel Visible
na False
. Krok 3 analizuje programowo zmianę właściwości Panel w Visible
odpowiedzi na kliknięcie przycisku, aby pokazać jeden interfejs, ukrywając drugi.
Poświęć chwilę, aby wyświetlić postęp w przeglądarce. Jak pokazano na rysunku 5, powinien zostać wyświetlony przycisk Przesyłka produktu procesu nad elementem GridView zawierającym listę produktów dziesięć naraz.
Rysunek 5. Widok GridView Listy możliwości sortowania i stronicowania produktów i ofert (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 2. Tworzenie interfejsu wstawiania
Po zakończeniu interfejsu wyświetlania jesteśmy gotowi do utworzenia interfejsu wstawiania. Na potrzeby tego samouczka utwórzmy interfejs wstawiania, który monituje o jedną wartość dostawcy i kategorii, a następnie umożliwia użytkownikowi wprowadzanie maksymalnie pięciu nazw produktów i wartości cen jednostkowych. Dzięki temu interfejsowi użytkownik może dodać jeden do pięciu nowych produktów, które mają taką samą kategorię i dostawcę, ale mają unikatowe nazwy produktów i ceny.
Zacznij od przeciągnięcia panelu z przybornika na Projektant, umieszczając go pod istniejącym DisplayInterface
Panelem. ID
Ustaw właściwość tego nowo dodanego panelu na InsertingInterface
i ustaw jej Visible
właściwość na False
. Dodamy kod, który ustawia InsertingInterface
właściwość Panel Visible
na True
w kroku 3. Usuń również zaznaczenie wartości właściwości i Width
paneliHeight
.
Następnie musimy utworzyć interfejs wstawiania, który został pokazany z powrotem na rysunku 1. Ten interfejs można utworzyć za pomocą różnych technik HTML, ale użyjemy dość prostego: czterokolumna, siedmioosobowa tabela.
Uwaga
Podczas wprowadzania znaczników dla elementów HTML <table>
preferuję korzystanie z widoku Źródło. Chociaż program Visual Studio ma narzędzia do dodawania <table>
elementów za pośrednictwem Projektant, Projektant wydaje się zbyt skłonny do wstrzykiwania nieoznakowanych style
ustawień do znaczników. Po utworzeniu <table>
znaczników zwykle wracam do Projektant, aby dodać kontrolki sieci Web i ustawić ich właściwości. Podczas tworzenia tabel ze wstępnie określonymi kolumnami i wierszami preferuję używanie statycznego kodu HTML, a nie kontrolki Sieci Web tabel , ponieważ wszystkie kontrolki sieci Web umieszczone w kontrolce Tabela Web mogą być dostępne tylko przy użyciu FindControl("controlID")
wzorca. Używam jednak kontrolek sieci Web tabel dla tabel o dynamicznym rozmiarze (tych, których wiersze lub kolumny są oparte na niektórych kryteriach bazy danych lub określonych przez użytkownika), ponieważ kontrolka tabela sieci Web może być konstruowana programowo.
Wprowadź następujące znaczniki w <asp:Panel>
tagach InsertingInterface
panelu:
<table class="DataWebControlStyle" cellspacing="0">
<tr class="BatchInsertHeaderRow">
<td class="BatchInsertLabel">Supplier:</td>
<td></td>
<td class="BatchInsertLabel">Category:</td>
<td></td>
</tr>
<tr class="BatchInsertRow">
<td class="BatchInsertLabel">Product:</td>
<td></td>
<td class="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<tr class="BatchInsertAlternatingRow">
<td class="BatchInsertLabel">Product:</td>
<td></td>
<td class="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<tr class="BatchInsertRow">
<td class="BatchInsertLabel">Product:</td>
<td></td>
<td class="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<tr class="BatchInsertAlternatingRow">
<td class="BatchInsertLabel">Product:</td>
<td></td>
<td class="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<tr class="BatchInsertRow">
<td class="BatchInsertLabel">Product:</td>
<td></td>
<td class="BatchInsertLabel">Price:</td>
<td></td>
</tr>
<tr class="BatchInsertFooterRow">
<td colspan="4">
</td>
</tr>
</table>
Ta <table>
adiustacja nie zawiera jeszcze żadnych kontrolek sieci Web. Dodamy je chwilowo. Należy pamiętać, że każdy <tr>
element zawiera określone ustawienie klasy CSS: BatchInsertHeaderRow
dla wiersza nagłówka, w którym zostanie wybrana lista rozwijana dostawcy i kategorii; w wierszu stopki, w którym zostaną dodane BatchInsertFooterRow
produkty z menu Wysyłka i Anuluj przyciski, oraz naprzemiennie BatchInsertRow
BatchInsertAlternatingRow
i wartości dla wierszy, które będą zawierać kontrolki Product i Unit Price TextBox. Utworzono odpowiednie klasy CSS w pliku w Styles.css
celu nadania interfejsowi wstawiania wygląd podobny do kontrolek GridView i DetailsView używanych w tych samouczkach. Poniżej przedstawiono te klasy CSS.
/*** Styles for ~/BatchData/BatchInsert.aspx tutorial ***/
.BatchInsertLabel
{
font-weight: bold;
text-align: right;
}
.BatchInsertHeaderRow td
{
color: White;
background-color: #900;
padding: 11px;
}
.BatchInsertFooterRow td
{
text-align: center;
padding-top: 5px;
}
.BatchInsertRow
{
}
.BatchInsertAlternatingRow
{
background-color: #fcc;
}
Po wprowadzeniu tego znacznika wróć do widoku Projekt. Powinno to <table>
być wyświetlane jako tabela czterokolumna, siedem wierszy w Projektant, jak pokazano na rysunku 6.
Rysunek 6. Interfejs wstawiania składa się z czterech kolumn, Seven-Row tabeli (kliknij, aby wyświetlić obraz pełnowymiarowy)
Teraz możemy dodać kontrolki sieci Web do interfejsu wstawiania. Przeciągnij dwie listy rozwijane z przybornika do odpowiednich komórek w tabeli jedną dla dostawcy i jedną dla kategorii.
Ustaw właściwość dostawcy DropDownList ID
na Suppliers
i powiąż ją z nowym obiektem ObjectDataSource o nazwie SuppliersDataSource
. Skonfiguruj nowe źródło ObjectDataSource, aby pobrać dane z SuppliersBLL
metody klasy s GetSuppliers
i ustawić listę rozwijaną kart UPDATE na wartość (Brak). Kliknij przycisk Zakończ, aby zakończyć kreatora.
Rysunek 7. Konfigurowanie obiektu ObjectDataSource do używania SuppliersBLL
metody klasy GetSuppliers
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Aby lista Suppliers
Rozwijana Lista rozwijana wyświetlała CompanyName
pole danych i używać SupplierID
pola danych jako wartości ListItem
.
Rysunek 8. Wyświetlanie CompanyName
pola danych i użycie SupplierID
jako wartości (kliknij, aby wyświetlić obraz pełnowymiarowy)
Nadaj drugiej liście DropDownList Categories
nazwę i powiąż ją z nowym obiektem ObjectDataSource o nazwie CategoriesDataSource
. Skonfiguruj obiekt CategoriesDataSource
ObjectDataSource do użycia CategoriesBLL
metody klasy s GetCategories
. Ustaw listy rozwijane na kartach UPDATE i DELETE na wartość (Brak), a następnie kliknij przycisk Zakończ, aby ukończyć pracę kreatora. Na koniec lista rozwijana Lista rozwijana wyświetla CategoryName
pole danych i użyj wartości CategoryID
jako wartości.
Po dodaniu tych dwóch list rozwijanych i powiązanych z odpowiednio skonfigurowanymi obiektami ObjectDataSources ekran powinien wyglądać podobnie do rysunku 9.
Rysunek 9. Wiersz nagłówka zawiera Suppliers
teraz listy rozwijane i Categories
(kliknij, aby wyświetlić obraz pełnowymiarowy)
Teraz musimy utworzyć pola TextBoxes, aby zebrać nazwę i cenę dla każdego nowego produktu. Przeciągnij kontrolkę TextBox z przybornika na Projektant dla każdej z pięciu nazw produktów i wierszy cen. ID
Ustaw właściwości pola TextBoxes na ProductName1
, , UnitPrice2
ProductName3
UnitPrice1
ProductName2
, UnitPrice3
i tak dalej.
Dodaj element CompareValidator po każdej cenie jednostkowej TextBoxes, ustawiając ControlToValidate
właściwość na odpowiednią ID
wartość . Operator
Ustaw również właściwość na wartość , ValueToCompare
na GreaterThanEqual
wartość 0 i Type
na Currency
wartość . Te ustawienia instruują narzędzie CompareValidator, aby upewnić się, że cena, jeśli została wprowadzona, jest prawidłową wartością waluty, która jest większa lub równa zero. Text
Ustaw właściwość na *, a ErrorMessage
cena musi być większa lub równa zero. Ponadto pomiń wszystkie symbole waluty.
Uwaga
Interfejs wstawiania nie zawiera żadnych kontrolek RequiredFieldValidator, mimo że ProductName
pole w Products
tabeli bazy danych nie zezwala na NULL
wartości. Dzieje się tak, ponieważ chcemy zezwolić użytkownikowi na wprowadzanie maksymalnie pięciu produktów. Jeśli na przykład użytkownik miał podać nazwę produktu i cenę jednostkową pierwszych trzech wierszy, pozostawiając ostatnie dwa wiersze puste, dodaliśmy tylko trzy nowe produkty do systemu. Ponieważ ProductName
jest to jednak wymagane, musimy programowo sprawdzić, czy w przypadku wprowadzenia ceny jednostkowej podano odpowiednią wartość nazwy produktu. Zajmiemy się tym zaewidencjonem w kroku 4.
Podczas sprawdzania poprawności danych wejściowych użytkownika narzędzie CompareValidator zgłasza nieprawidłowe dane, jeśli wartość zawiera symbol waluty. Dodaj $ przed każdą ceną jednostkową TextBoxes, aby służyć jako wizualny sygnał, który nakazuje użytkownikowi pominięcie symbolu waluty podczas wprowadzania ceny.
Na koniec dodaj kontrolkę ValidationSummary w InsertingInterface
panelu, ustaw jej ShowMessageBox
właściwość na True
i jej ShowSummary
właściwość na False
. W przypadku tych ustawień, jeśli użytkownik wprowadzi nieprawidłową wartość ceny jednostkowej, gwiazdka pojawi się obok kontrolek TextBox, a właściwość ValidationSummary wyświetli pole komunikatu po stronie klienta, które pokazuje wcześniej określony komunikat o błędzie.
Na tym etapie ekran powinien wyglądać podobnie do rysunku 10.
Rysunek 10. Interfejs wstawiania zawiera teraz pola tekstowe dla nazw produktów i cen (kliknij, aby wyświetlić obraz pełnowymiarowy)
Następnie musimy dodać przyciski Dodaj produkty z wysyłki i Anuluj do wiersza stopki. Przeciągnij dwa kontrolki Przycisk z przybornika do stopki interfejsu wstawiania, ustawiając właściwości Przyciski ID
na AddProducts
i CancelButton
i Text
właściwości, aby odpowiednio dodać produkty z wysyłki i anulowania. Ponadto ustaw właściwość s CausesValidation
kontrolki CancelButton
na false
.
Na koniec musimy dodać kontrolkę Sieć Web Etykieta, która będzie wyświetlać komunikaty o stanie dla dwóch interfejsów. Na przykład gdy użytkownik pomyślnie doda nową przesyłkę produktów, chcemy wrócić do interfejsu wyświetlania i wyświetlić komunikat potwierdzający. Jeśli jednak użytkownik podaje cenę nowego produktu, ale pozostawia nazwę produktu, musimy wyświetlić komunikat ostrzegawczy, ponieważ ProductName
pole jest wymagane. Ponieważ potrzebujemy tego komunikatu do wyświetlenia dla obu interfejsów, umieść go w górnej części strony poza panelami.
Przeciągnij kontrolkę Etykieta sieci Web z przybornika do góry strony w Projektant. ID
Ustaw właściwość na StatusLabel
, wyczyść Text
właściwość i ustaw Visible
dla właściwości i EnableViewState
wartość False
. Jak widzieliśmy w poprzednich samouczkach, ustawienie EnableViewState
właściwości w celu False
pozwala nam programowo zmienić wartości właściwości Etykieta i automatycznie przywrócić ich wartości domyślne w kolejnym poście zwrotnym. Upraszcza to kod wyświetlania komunikatu o stanie w odpowiedzi na akcję użytkownika, która znika po kolejnym poście zwrotnym. Na koniec ustaw właściwość kontrolki StatusLabel
CssClass
na Ostrzeżenie, która jest nazwą klasy CSS zdefiniowanej w tym, która wyświetla tekst w Styles.css
dużej, kursywie, pogrubionej, czerwonej czcionki.
Rysunek 11 przedstawia Projektant programu Visual Studio po dodaniu i skonfigurowaniu etykiety.
Rysunek 11. Umieść kontrolkę StatusLabel
nad kontrolkami Dwóch paneli (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 3. Przełączanie między interfejsami wyświetlania i wstawiania
W tym momencie ukończyliśmy znaczniki dla interfejsów wyświetlania i wstawiania, ale nadal pozostajemy z dwoma zadaniami:
- Przełączanie między interfejsami wyświetlania i wstawiania
- Dodawanie produktów do bazy danych
Obecnie interfejs wyświetlania jest widoczny, ale interfejs wstawiania jest ukryty. Dzieje się tak, ponieważ DisplayInterface
właściwość Panel Visible
jest ustawiona na True
wartość (wartość domyślna), podczas gdy InsertingInterface
właściwość Panel Visible
jest ustawiona na False
wartość . Aby przełączyć się między dwoma interfejsami, wystarczy przełączyć każdą wartość właściwości kontrolki Visible
.
Chcemy przejść z interfejsu wyświetlania do interfejsu wstawiania po kliknięciu przycisku Przesyłka produktu procesu. W związku z tym utwórz procedurę obsługi zdarzeń dla tego zdarzenia przycisku Click
, które zawiera następujący kod:
Protected Sub ProcessShipment_Click(sender As Object, e As EventArgs) _
Handles ProcessShipment.Click
DisplayInterface.Visible = False
InsertingInterface.Visible = True
End Sub
Ten kod powoduje po prostu ukrycie DisplayInterface
panelu i wyświetlenie InsertingInterface
panelu.
Następnie utwórz programy obsługi zdarzeń dla kontrolek Dodaj produkty z wysyłki i Przycisku anulowania w interfejsie wstawiania. Po kliknięciu jednego z tych przycisków musimy wrócić do interfejsu wyświetlania. Utwórz Click
programy obsługi zdarzeń dla obu kontrolek Przycisk, aby wywoływać ReturnToDisplayInterface
metodę , którą dodamy chwilowo. Oprócz ukrywania InsertingInterface
panelu i wyświetlania DisplayInterface
panelu ReturnToDisplayInterface
metoda musi zwrócić kontrolki sieci Web do stanu wstępnej edycji. Obejmuje to ustawienie właściwości DropDownLists SelectedIndex
na wartość 0 i wyczyszczenie Text
właściwości kontrolek TextBox.
Uwaga
Rozważ, co może się zdarzyć, jeśli nie przywróciliśmy kontrolek do stanu przed edycją przed powrotem do interfejsu wyświetlania. Użytkownik może kliknąć przycisk Przetwarzaj przesyłkę produktu, wprowadzić produkty z przesyłki, a następnie kliknąć pozycję Dodaj produkty z przesyłki. Spowoduje to dodanie produktów i zwrócenie użytkownika do interfejsu wyświetlania. W tym momencie użytkownik może chcieć dodać kolejną przesyłkę. Po kliknięciu przycisku Przetwarzaj przesyłkę produktu zostaną one zwrócone do interfejsu wstawiania, ale opcje Lista rozwijanaLista i wartości TextBox nadal będą wypełniane ich poprzednimi wartościami.
Protected Sub AddProducts_Click(sender As Object, e As EventArgs) _
Handles AddProducts.Click
' TODO: Save the products
' Revert to the display interface
ReturnToDisplayInterface()
End Sub
Protected Sub CancelButton_Click(sender As Object, e As EventArgs) _
Handles CancelButton.Click
' Revert to the display interface
ReturnToDisplayInterface()
End Sub
Const firstControlID As Integer = 1
Const lastControlID As Integer = 5
Private Sub ReturnToDisplayInterface()
' Reset the control values in the inserting interface
Suppliers.SelectedIndex = 0
Categories.SelectedIndex = 0
For i As Integer = firstControlID To lastControlID
CType(InsertingInterface.FindControl _
("ProductName" + i.ToString()), TextBox).Text = String.Empty
CType(InsertingInterface.FindControl _
("UnitPrice" + i.ToString()), TextBox).Text = String.Empty
Next
DisplayInterface.Visible = True
InsertingInterface.Visible = False
End Sub
Oba Click
programy obsługi zdarzeń po prostu wywołają metodę ReturnToDisplayInterface
, chociaż wrócimy do procedury obsługi zdarzeń Dodaj produkty z wysyłki Click
w kroku 4 i dodamy kod, aby zapisać produkty. ReturnToDisplayInterface
rozpoczyna się od zwrócenia listy rozwijanej Suppliers
i Categories
do ich pierwszych opcji. Dwie stałe firstControlID
i lastControlID
oznaczą wartości indeksu początkowego i końcowego kontrolki używane w nazewnictwie nazwy produktu i ceny jednostkowej TextBoxes w interfejsie wstawiania i są używane w granicach For
pętli, która ustawia Text
właściwości kontrolek TextBox z powrotem na pusty ciąg. Na koniec właściwości Panele Visible
są resetowane, aby interfejs wstawiania był ukryty i wyświetlany interfejs wyświetlania.
Poświęć chwilę, aby przetestować tę stronę w przeglądarce. Podczas pierwszej wizyty na stronie powinien zostać wyświetlony interfejs wyświetlania, jak pokazano na rysunku 5. Kliknij przycisk Przetwarzaj przesyłkę produktu. Strona zostanie wycofana i powinna zostać wyświetlony interfejs wstawiania, jak pokazano na rysunku 12. Kliknięcie przycisków Dodaj produkty z wysyłki lub Anuluj powoduje powrót do interfejsu wyświetlania.
Uwaga
Podczas przeglądania interfejsu wstawiania poświęć chwilę, aby przetestować moduły CompareValidators w cenie jednostkowej TextBoxes. Po kliknięciu przycisku Dodaj produkty z przesyłki z nieprawidłowymi wartościami waluty lub cenami o wartości mniejszej niż zero powinna zostać wyświetlona ostrzeżenie po stronie klienta.
Rysunek 12. Interfejs wstawiania jest wyświetlany po kliknięciu przycisku Przesyłka produktu procesu (kliknij, aby wyświetlić obraz pełnowymiarowy)
Krok 4. Dodawanie produktów
Wszystko, co pozostaje w tym samouczku, to zapisanie produktów w bazie danych w procedurze obsługi zdarzeń Dodaj produkty z przycisku Click
wysyłki. Można to zrobić, tworząc i ProductsDataTable
dodając ProductsRow
wystąpienie dla każdej dostarczonej nazwy produktów. Po dodaniu tych ProductsRow
elementów wykonamy wywołanie ProductsBLL
metody klasy UpdateWithTransaction
przekazującej ProductsDataTable
element . Pamiętaj, że metoda, która została utworzona z powrotem w samouczku Zawijanie UpdateWithTransaction
modyfikacji bazy danych w ramach transakcji , przekazuje ProductsDataTable
metodę ProductsTableAdapter
do metody "s UpdateWithTransaction
". W tym miejscu jest uruchamiana transakcja ADO.NET, a obiekt TableAdapter wystawia instrukcję INSERT
do bazy danych dla każdego dodanego ProductsRow
w tabeli DataTable. Zakładając, że wszystkie produkty są dodawane bez błędu, transakcja zostanie zatwierdzona, w przeciwnym razie zostanie wycofana.
Kod obsługi zdarzeń Dodaj produkty z przycisku Click
wysyłki również musi wykonać trochę sprawdzania błędów. Ponieważ nie ma elementów RequiredFieldValidator używanych w interfejsie wstawiania, użytkownik może wprowadzić cenę produktu, pomijając jego nazwę. Ponieważ nazwa produktu jest wymagana, jeśli taki warunek rozwija się, musimy powiadomić użytkownika i nie kontynuować wstawiania. Click
Kompletny kod obsługi zdarzeń jest następujący:
Protected Sub AddProducts_Click(sender As Object, e As EventArgs) _
Handles AddProducts.Click
' Make sure that the UnitPrice CompareValidators report valid data...
If Not Page.IsValid Then Exit Sub
' Add new ProductsRows to a ProductsDataTable...
Dim products As New Northwind.ProductsDataTable()
For i As Integer = firstControlID To lastControlID
' Read in the values for the product name and unit price
Dim productName As String = CType(InsertingInterface.FindControl _
("ProductName" + i.ToString()), TextBox).Text.Trim()
Dim unitPrice As String = CType(InsertingInterface.FindControl _
("UnitPrice" + i.ToString()), TextBox).Text.Trim()
' Ensure that if unitPrice has a value, so does productName
If unitPrice.Length > 0 AndAlso productName.Length = 0 Then
' Display a warning and exit this event handler
StatusLabel.Text = "If you provide a unit price you must also
include the name of the product."
StatusLabel.Visible = True
Exit Sub
End If
' Only add the product if a product name value is provided
If productName.Length > 0 Then
' Add a new ProductsRow to the ProductsDataTable
Dim newProduct As Northwind.ProductsRow = products.NewProductsRow()
' Assign the values from the web page
newProduct.ProductName = productName
newProduct.SupplierID = Convert.ToInt32(Suppliers.SelectedValue)
newProduct.CategoryID = Convert.ToInt32(Categories.SelectedValue)
If unitPrice.Length > 0 Then
newProduct.UnitPrice = Convert.ToDecimal(unitPrice)
End If
' Add any "default" values
newProduct.Discontinued = False
newProduct.UnitsOnOrder = 0
products.AddProductsRow(newProduct)
End If
Next
' If we reach here, see if there were any products added
If products.Count > 0 Then
' Add the new products to the database using a transaction
Dim productsAPI As New ProductsBLL()
productsAPI.UpdateWithTransaction(products)
' Rebind the data to the grid so that the products just added are displayed
ProductsGrid.DataBind()
' Display a confirmation (don't use the Warning CSS class, though)
StatusLabel.CssClass = String.Empty
StatusLabel.Text = String.Format( _
"{0} products from supplier {1} have been " & _
"added and filed under category {2}.", _
products.Count, Suppliers.SelectedItem.Text, Categories.SelectedItem.Text)
StatusLabel.Visible = True
' Revert to the display interface
ReturnToDisplayInterface()
Else
' No products supplied!
StatusLabel.Text =
"No products were added. Please enter the " & _
"product names and unit prices in the textboxes."
StatusLabel.Visible = True
End If
End Sub
Procedura obsługi zdarzeń rozpoczyna się od upewnienia się, że Page.IsValid
właściwość zwraca wartość .True
Jeśli zwróci False
wartość , oznacza to, że co najmniej jeden element CompareValidator zgłasza nieprawidłowe dane. W takim przypadku nie chcemy próbować wstawić wprowadzonych produktów lub wystąpi wyjątek podczas próby przypisania wartości ceny jednostkowej wprowadzonej przez użytkownika do ProductsRow
UnitPrice
właściwości.
Następnie zostanie utworzone nowe ProductsDataTable
wystąpienie (products
). Pętla For
służy do iteracji przez nazwę produktu i cenę jednostkową TextBoxes, a Text
właściwości są odczytywane do zmiennych productName
lokalnych i unitPrice
. Jeśli użytkownik wprowadził wartość dla ceny jednostkowej, ale nie dla odpowiedniej nazwy produktu, zostanie wyświetlony komunikat Jeśli podasz cenę jednostkową, StatusLabel
musisz również dołączyć nazwę produktu i program obsługi zdarzeń zostanie zakończona.
Jeśli podano nazwę produktu, zostanie utworzone nowe ProductsRow
wystąpienie przy użyciu ProductsDataTable
metody s NewProductsRow
. Ta nowa ProductsRow
właściwość wystąpienia ProductName
jest ustawiona na bieżącą nazwę produktu TextBox, podczas gdy SupplierID
właściwości i CategoryID
są przypisane do SelectedValue
właściwości list DropDownLists w nagłówku interfejsu wstawiania. Jeśli użytkownik wprowadził wartość dla ceny produktu, zostanie przypisany do ProductsRow
właściwości wystąpienia UnitPrice
. W przeciwnym razie właściwość pozostanie nieprzypisane, co spowoduje NULL
, że wartość elementu UnitPrice
w bazie danych zostanie przypisana. Discontinued
Na koniec właściwości i UnitsOnOrder
są przypisane odpowiednio do wartości False
zakodowanych na kodzie i 0.
Po przypisaniu właściwości do ProductsRow
wystąpienia zostanie ono dodane do obiektu ProductsDataTable
.
Po zakończeniu For
pętli sprawdzamy, czy zostały dodane jakiekolwiek produkty. Użytkownik może w końcu kliknąć pozycję Dodaj produkty z przesyłki przed wprowadzeniem nazw produktów lub cen. Jeśli w metodzie ProductsDataTable
jest co najmniej jeden produkt , ProductsBLL
wywoływana jest metoda klasy s UpdateWithTransaction
. Następnie dane zostaną odzyskane do kontrolki ProductsGrid
GridView, aby nowo dodane produkty pojawiły się w interfejsie wyświetlania. Element StatusLabel
jest aktualizowany w celu wyświetlenia komunikatu potwierdzenia i ReturnToDisplayInterface
wywołania, ukrywania interfejsu wstawiania i wyświetlania interfejsu wyświetlania.
Jeśli nie wprowadzono żadnych produktów, interfejs wstawiania pozostaje wyświetlany, ale komunikat Nie dodano żadnych produktów. Wprowadź nazwy produktów i ceny jednostkowe w polach tekstowych.
Na rysunku 13, 14 i 15 przedstawiono wstawiania i wyświetlania interfejsów w akcji. Na rysunku 13 użytkownik wprowadził wartość ceny jednostkowej bez odpowiedniej nazwy produktu. Rysunek 14 przedstawia interfejs wyświetlania po pomyślnym dodaniu trzech nowych produktów, podczas gdy rysunek 15 przedstawia dwa z nowo dodanych produktów w elemecie GridView (trzeci z nich znajduje się na poprzedniej stronie).
Rysunek 13. Nazwa produktu jest wymagana podczas wprowadzania ceny jednostkowej (kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 14. Dodano trzy nowe veggies dla dostawcy Mayumi s (kliknij, aby wyświetlić obraz pełnowymiarowy)
Rysunek 15. Nowe produkty można znaleźć na ostatniej stronie widoku GridView (kliknij, aby wyświetlić obraz pełnowymiarowy)
Uwaga
Logika wstawiania wsadowego używana w tym samouczku opakowuje wstawki w zakresie transakcji. Aby to sprawdzić, celowo wprowadź błąd na poziomie bazy danych. Na przykład zamiast przypisywać nową ProductsRow
właściwość wystąpienia CategoryID
do wybranej wartości w liście RozwijanejList Categories
, przypisz ją do wartości takiej jak i * 5
. Oto i
indeksator pętli i ma wartości z zakresu od 1 do 5. W związku z tym podczas dodawania co najmniej dwóch produktów w partii wstaw pierwszy produkt będzie miał prawidłową CategoryID
wartość (5), ale kolejne produkty będą miały CategoryID
wartości, które nie są zgodne z CategoryID
wartościami w Categories
tabeli. Efekt netto polega na tym, że podczas gdy pierwszy INSERT
powiedzie się, kolejne zakończy się niepowodzeniem z naruszeniem ograniczenia klucza obcego. Ponieważ wstawianie wsadowe jest niepodzielne, pierwszy INSERT
zostanie wycofany, zwracając bazę danych do stanu przed rozpoczęciem procesu wstawiania wsadowego.
Podsumowanie
W tym i poprzednich dwóch samouczkach utworzyliśmy interfejsy, które umożliwiają aktualizowanie, usuwanie i wstawianie partii danych, z których wszystkie korzystały z obsługi transakcji dodane do warstwy dostępu do danych w samouczku Zawijanie modyfikacji bazy danych w ramach transakcji . W przypadku niektórych scenariuszy takie interfejsy użytkownika przetwarzania wsadowego znacznie zwiększają wydajność użytkownika końcowego, zmniejszając liczbę kliknięć, po powrocie zwrotnym i przełączniki kontekstowe klawiatury do myszy, zachowując jednocześnie integralność danych bazowych.
W tym samouczku przedstawiono pracę z danymi wsadowymi. W następnym zestawie samouczków przedstawiono różne zaawansowane scenariusze warstwy dostępu do danych, w tym przy użyciu procedur składowanych w metodach tableAdapter, konfigurowania ustawień połączenia i poziomu poleceń w dal, szyfrowania parametrów połączenia i nie tylko!
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 ciągu 24 godzin. Można do niego dotrzeć 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 sprawdzona przez wielu pomocnych recenzentów. Recenzenci w tym samouczku byli Hilton Giesenow i S ren Jacob Lauritsen. Chcesz przejrzeć nadchodzące artykuły MSDN? Jeśli tak, upuść mi wiersz pod adresem mitchell@4GuysFromRolla.com.