Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
von Scott Mitchell
Erfahren Sie, wie Sie mehrere Datenbankdatensätze in einem einzigen Vorgang einfügen. In der Benutzeroberflächenebene erweitern wir die GridView, um dem Benutzer die Eingabe mehrerer neuer Datensätze zu ermöglichen. In der Datenzugriffsschicht umschließen wir die verschiedenen Insert-Operationen innerhalb einer Transaktion, um sicherzustellen, dass alle Einfügungen erfolgreich sind oder alle Einfügungen rückgängig gemacht werden.
Einleitung
Im Tutorial zur Batchaktualisierung haben wir uns mit dem Anpassen des GridView-Steuerelements befasst, um eine Schnittstelle bereitzustellen, in der mehrere Datensätze bearbeitet werden können. Der Benutzer, der die Seite besucht, kann eine Reihe von Änderungen vornehmen und dann mit einem einzigen Klick auf eine Schaltfläche eine Batch-Aktualisierung durchführen. In Situationen, in denen Benutzer häufig viele Datensätze auf einmal aktualisieren, kann eine solche Schnittstelle im Vergleich zu den standardmäßigen Bearbeitungsfunktionen pro Zeile, die erstmals im Tutorial Überblick über das Einfügen, Aktualisieren und Löschen von Daten untersucht wurden, unzählige Klicks und Kontextwechsel zwischen Tastatur und Maus einsparen.
Dieses Konzept kann auch beim Hinzufügen von Datensätzen angewendet werden. Stellen Sie sich vor, dass wir hier bei Northwind Traders häufig Sendungen von Lieferanten erhalten, die eine Reihe von Produkten für eine bestimmte Kategorie enthalten. Ein Beispiel: Wir erhalten eine Lieferung von sechs verschiedenen Tee- und Kaffeeprodukten von Tokyo Traders. Wenn ein Benutzer die sechs Produkte nacheinander über ein DetailsView-Steuerelement eingibt, muss er viele der gleichen Werte immer wieder auswählen: Er muss die gleiche Kategorie (Getränke), den gleichen Lieferanten (Tokyo Traders), den gleichen Auslaufwert (False) und die gleichen Einheiten für den Bestellwert (0) auswählen. Diese sich wiederholende Dateneingabe ist nicht nur zeitaufwändig, sondern auch fehleranfällig.
Mit ein wenig Arbeit können wir eine Batch-Einfügeschnittstelle erstellen, die es dem Benutzer ermöglicht, den Lieferanten und die Kategorie einmal auszuwählen, eine Reihe von Produktnamen und Stückpreisen einzugeben und dann auf eine Schaltfläche zu klicken, um die neuen Produkte zur Datenbank hinzuzufügen (siehe Abbildung 1). Wenn jedes Produkt hinzugefügt wird, werden den Datenfeldern und ProductName
UnitPrice
die in den Textfeldern eingegebenen Werte zugewiesen, während den Werten "und" CategoryID
SupplierID
die Werte aus den Dropdown-Listen oben im Formular zugewiesen werden.
Discontinued
Die UnitsOnOrder
und-Werte werden auf die hartcodierten Werte bzwFalse
. 0 festgelegt.
Abbildung 1: Die Schnittstelle zum Einfügen von Stapeln (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
In diesem Tutorial erstellen wir eine Seite, die die in Abbildung 1 gezeigte Schnittstelle zum Einfügen von Stapeln implementiert. Wie bei den beiden vorherigen Tutorials werden wir die Einfügungen in den Bereich einer Transaktion einschließen, um die Atomarität sicherzustellen. Los geht's!
Schritt 1: Erstellen der Anzeigeoberfläche
Dieses Tutorial besteht aus einer einzelnen Seite, die in zwei Bereiche unterteilt ist: einen Anzeigebereich und einen Einfügebereich. Die Anzeigeoberfläche, die wir in diesem Schritt erstellen, zeigt die Produkte in einer GridView an und enthält eine Schaltfläche mit dem Titel Produktlieferung verarbeiten. Wenn Sie auf diese Schaltfläche klicken, wird die Anzeigeschnittstelle durch die Einfügeschnittstelle ersetzt, die in Abbildung 1 dargestellt ist. Die Anzeigeoberfläche wird angezeigt, nachdem Sie auf die Schaltflächen Produkte aus Versand hinzufügen oder Stornieren geklickt haben. In Schritt 2 erstellen wir die Einfügeschnittstelle.
Beim Erstellen einer Seite mit zwei Schnittstellen, von denen jeweils nur eine sichtbar ist, wird jede Schnittstelle in der Regel in einem Panel-Websteuerelement platziert, das als Container für andere Steuerelemente dient. Daher verfügt unsere Seite über zwei Panel-Steuerelemente, eines für jede Schnittstelle.
Öffnen Sie zunächst die BatchInsert.aspx
Seite im BatchData
Ordner, und ziehen Sie ein Panel aus der Toolbox auf den Designer (siehe Abbildung 2). Legen Sie die Eigenschaft von Panel s ID
auf DisplayInterface
fest. Wenn Sie den Bereich zum Designer hinzufügen, werden die Height
Eigenschaften und Width
auf 50 Pixel bzw. 125 Pixel festgelegt. Löschen Sie diese Eigenschaftswerte aus dem Eigenschaftenfenster.
Abbildung 2: Ziehen eines Panels aus der Toolbox auf den Designer (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Ziehen Sie als Nächstes ein Button- und ein GridView-Steuerelement in den Bereich. Legen Sie die Eigenschaft ID
der Schaltfläche auf ProcessShipment
und ihre Text
Eigenschaft auf Produktversand verarbeiten fest. Legen Sie die GridView-Eigenschaft ID
auf und binden Sie sie von ihrem Smarttag an ProductsGrid
eine neue ObjectDataSource mit dem Namen ProductsDataSource
. Konfigurieren Sie die ObjectDataSource so, dass sie ihre Daten aus der ProductsBLL
Klasse und der GetProducts
Methode zieht. Da diese GridView nur zum Anzeigen von Daten verwendet wird, legen Sie die Dropdownlisten auf den Registerkarten UPDATE, INSERT und DELETE auf (Keine) fest. Klicken Sie auf Fertig stellen, um den Assistenten zum Konfigurieren von Datenquellen abzuschließen.
Abbildung 3: Anzeigen der von der ProductsBLL
Methode der Klasse s GetProducts
zurückgegebenen Daten (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Abbildung 4: Festlegen der Drop-Down Listen in den Registerkarten UPDATE, INSERT und DELETE auf (Keine) (Klicken, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des ObjectDataSource-Assistenten fügt Visual Studio BoundFields und ein CheckBoxField für die Produktdatenfelder hinzu. Entfernen Sie alle Felder bis auf die Felder , ProductName
, , CategoryName
SupplierName
, und UnitPrice
.Discontinued
Fühlen Sie sich frei, ästhetische Anpassungen vorzunehmen. Ich habe mich entschieden, das UnitPrice
Feld als Währungswert zu formatieren, die Felder neu angeordnet und einige der Feldwerte HeaderText
umbenannt. Konfigurieren Sie die GridView auch so, dass sie Auslagerungs- und Sortierunterstützung enthält, indem Sie die Kontrollkästchen "Paging aktivieren" und "Sortierung aktivieren" im Smarttag von GridView aktivieren.
Nach dem Hinzufügen der Steuerelemente Panel, Button, GridView und ObjectDataSource und dem Anpassen der GridView-Felder sollte das deklarative Markup der Seite in etwa wie folgt aussehen:
<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>
Beachten Sie, dass das Markup für Button und GridView innerhalb der öffnenden und schließenden <asp:Panel>
Tags angezeigt wird. Da sich diese Steuerelemente innerhalb des DisplayInterface
Panels befinden, können wir sie ausblenden, indem wir einfach die Eigenschaft von Visible
Panel auf False
setzen. Schritt 3 befasst sich mit dem programmgesteuerten Ändern der Panel-Eigenschaft Visible
als Reaktion auf einen Schaltflächenklick, um eine Schnittstelle anzuzeigen, während die andere ausgeblendet wird.
Nehmen Sie sich einen Moment Zeit, um unseren Fortschritt über einen Browser anzuzeigen. Wie Abbildung 5 zeigt, sollte über einer GridView die Schaltfläche Produktlieferung verarbeiten angezeigt werden, in der jeweils zehn Produkte aufgelistet sind.
Abbildung 5: Die GridView listet die Produkte auf und bietet Sortier- und Paging-Funktionen (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Schritt 2: Erstellen der Einfügeschnittstelle
Nachdem die Anzeigeschnittstelle fertiggestellt ist, können wir mit der Erstellung der Einfügeschnittstelle beginnen. In diesem Tutorial erstellen wir eine Einfügeschnittstelle, die zur Eingabe eines einzelnen Lieferanten- und Kategoriewerts auffordert und es dem Benutzer dann ermöglicht, bis zu fünf Produktnamen und Stückpreiswerte einzugeben. Mit dieser Schnittstelle kann der Benutzer ein bis fünf neue Produkte hinzufügen, die alle dieselbe Kategorie und denselben Lieferanten haben, aber eindeutige Produktnamen und Preise haben.
Ziehen Sie zunächst ein Panel aus der Toolbox auf den Designer, und platzieren Sie es unter dem vorhandenen DisplayInterface
Panel. Legen Sie die ID
Eigenschaft dieses neu hinzugefügten Panels auf InsertingInterface
fest, und legen Sie seine Visible
Eigenschaft auf False
fest. In Schritt 3 fügen wir Code hinzu, der die InsertingInterface
Panel-Eigenschaft Visible
festlegtTrue
. Löschen Sie auch die Panel- und Height
EigenschaftswerteWidth
.
Als Nächstes müssen wir die Einfügeschnittstelle erstellen, die in Abbildung 1 gezeigt wurde. Diese Schnittstelle kann durch eine Vielzahl von HTML-Techniken erstellt werden, aber wir werden eine ziemlich einfache verwenden: eine vierspaltige, siebenzeilige Tabelle.
Hinweis
Bei der Eingabe von Markup für HTML-Elemente <table>
verwende ich am liebsten die Quellansicht. Visual Studio verfügt zwar über Tools zum Hinzufügen <table>
von Elementen über den Designer, aber der Designer scheint nur allzu bereit zu sein, ungefragte style
Einstellungen in das Markup einzufügen. Nachdem ich das <table>
Markup erstellt habe, kehre ich in der Regel zum Designer zurück, um die Websteuerelemente hinzuzufügen und ihre Eigenschaften festzulegen. Beim Erstellen von Tabellen mit vordefinierten Spalten und Zeilen bevorzuge ich die Verwendung von statischem HTML anstelle des Table Web-Steuerelements , da auf alle Web-Steuerelemente, die in einem Table Web-Steuerelement platziert sind, nur über das FindControl("controlID")
Muster zugegriffen werden kann. Ich verwende jedoch Tabellenwebsteuerelemente für Tabellen mit dynamischer Größe (Tabellen, deren Zeilen oder Spalten auf einer Datenbank oder benutzerdefinierten Kriterien basieren), da das Tabellenwebsteuerelement programmgesteuert erstellt werden kann.
Geben Sie das folgende Markup in die <asp:Panel>
Tags des InsertingInterface
Panels ein:
<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>
Dieses <table>
Markup enthält noch keine Websteuerelemente, die wir in Kürze hinzufügen werden. Beachten Sie, dass jedes <tr>
Element eine bestimmte CSS-Klasseneinstellung enthält: BatchInsertHeaderRow
für die Kopfzeile, in der sich die DropDownLists für Lieferanten und Kategorien befinden, für die Fußzeile, BatchInsertFooterRow
in der sich die Schaltflächen Produkte aus Versand hinzufügen und Stornieren befinden, sowie abwechselnd BatchInsertRow
Werte BatchInsertAlternatingRow
für die Zeilen, die die TextBox-Steuerelemente für Produkt und Stückpreis enthalten. Ich habe entsprechende CSS-Klassen in der Styles.css
Datei erstellt, um der Einfügeschnittstelle ein ähnliches Aussehen zu verleihen wie den GridView- und DetailsView-Steuerelementen, die wir in diesen Tutorials verwendet haben. Diese CSS-Klassen sind unten dargestellt.
/*** 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;
}
Wenn Sie dieses Markup eingegeben haben, kehren Sie zur Entwurfsansicht zurück. Dies <table>
sollte im Designer als vierspaltige, siebenzeilige Tabelle angezeigt werden, wie in Abbildung 6 dargestellt.
Abbildung 6: Die Einfügeschnittstelle besteht aus einer vierspaltigen, Seven-Row Tabelle (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Wir sind jetzt bereit, die Websteuerelemente zur Einfügeschnittstelle hinzuzufügen. Ziehen Sie zwei Dropdown-Listen aus der Toolbox in die entsprechenden Zellen in der Tabelle, eine für den Lieferanten und eine für die Kategorie.
Legen Sie die DropDownList-Eigenschaft des ID
Lieferanten auf Suppliers
fest, und binden Sie sie an eine neue ObjectDataSource mit dem Namen SuppliersDataSource
. Konfigurieren Sie die neue ObjectDataSource so, dass ihre Daten aus der SuppliersBLL
Methode der Klasse s abgerufen werden, GetSuppliers
und legen Sie die Dropdownliste der Registerkarte UPDATE auf (Keine) fest. Klicken Sie auf Fertig stellen, um den Assistenten abzuschließen.
Abbildung 7: Konfigurieren von ObjectDataSource für die Verwendung der SuppliersBLL
Methode der Klasse s GetSuppliers
(Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Lassen Sie die DropDownList das Suppliers
Datenfeld anzeigen, CompanyName
und verwenden Sie das SupplierID
Datenfeld als s-WertListItem
.
Abbildung 8: Anzeigen des Datenfelds CompanyName
und Verwenden SupplierID
als Wert (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Benennen Sie die zweite DropDownList, Categories
und binden Sie sie an eine neue ObjectDataSource mit dem Namen CategoriesDataSource
. Konfigurieren Sie ObjectDataSource CategoriesDataSource
für die Verwendung der CategoriesBLL
Methode der Klasse s GetCategories
. Legen Sie die Dropdownlisten auf den Registerkarten UPDATE und DELETE auf (Keine) fest, und klicken Sie auf Fertig stellen, um den Assistenten abzuschließen. Lassen Sie abschließend die DropDownList das CategoryName
Datenfeld anzeigen, und verwenden Sie das CategoryID
als Wert.
Nachdem diese beiden DropDownLists hinzugefügt und an entsprechend konfigurierte ObjectDataSources gebunden wurden, sollte der Bildschirm in etwa wie in Abbildung 9 aussehen.
Abbildung 9: Die Kopfzeile enthält jetzt die Suppliers
Dropdown-Listen und Categories
(Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen).
Wir müssen nun die TextBoxes erstellen, um den Namen und den Preis für jedes neue Produkt zu erfassen. Ziehen Sie ein TextBox-Steuerelement aus der Toolbox auf den Designer für jede der fünf Produktnamen- und Preiszeilen. Legen Sie die ID
Eigenschaften der TextBoxes auf ProductName1
, UnitPrice1
, ProductName2
, , UnitPrice2
, ProductName3
usw UnitPrice3
. fest.
Fügen Sie nach jedem Textfeld pro Stückpreis einen CompareValidator hinzu, und legen Sie die ControlToValidate
Eigenschaft auf die entsprechende ID
. Legen Sie die Operator
Eigenschaft außerdem auf GreaterThanEqual
, ValueToCompare
auf 0 und Type
auf Currency
fest. Diese Einstellungen weisen den CompareValidator an, sicherzustellen, dass der Preis, falls eingegeben, ein gültiger Währungswert ist, der größer oder gleich Null ist. Legen Sie die Text
Eigenschaft auf * und ErrorMessage
auf Der Preis muss größer oder gleich Null sein. Bitte lassen Sie auch alle Währungssymbole weg.
Hinweis
Die Einfügeschnittstelle enthält keine RequiredFieldValidator-Steuerelemente, obwohl das ProductName
Feld in der Products
Datenbanktabelle keine Werte zulässt NULL
. Dies liegt daran, dass wir dem Benutzer die Eingabe von bis zu fünf Produkten ermöglichen möchten. Wenn der Benutzer z. B. den Produktnamen und den Stückpreis für die ersten drei Zeilen eingibt und die letzten beiden Zeilen leer lässt, fügen wir dem System einfach drei neue Produkte hinzu. Da ProductName
jedoch erforderlich ist, müssen wir programmgesteuert überprüfen, um sicherzustellen, dass bei der Eingabe eines Stückpreises ein entsprechender Wert für den Produktnamen angegeben wird. Wir werden diese Überprüfung in Schritt 4 angehen.
Bei der Validierung der Benutzereingabe meldet der CompareValidator ungültige Daten, wenn der Wert ein Währungssymbol enthält. Fügen Sie ein $ vor jedes der Textfelder für den Stückpreis ein, um als visuellen Hinweis zu dienen, der den Benutzer anweist, das Währungssymbol bei der Eingabe des Preises wegzulassen.
Fügen Sie abschließend ein ValidationSummary-Steuerelement innerhalb des InsertingInterface
Panels hinzu, legen Sie seine ShowMessageBox
Eigenschaft auf True
und seine ShowSummary
Eigenschaft auf False
fest. Wenn der Benutzer mit diesen Einstellungen einen ungültigen Stückpreiswert eingibt, wird ein Sternchen neben den fehlerhaften TextBox-Steuerelementen angezeigt, und ValidationSummary zeigt ein clientseitiges Meldungsfeld an, in dem die zuvor angegebene Fehlermeldung angezeigt wird.
Zu diesem Zeitpunkt sollte der Bildschirm in etwa wie in Abbildung 10 aussehen.
Abbildung 10: Die Einfügeschnittstelle enthält jetzt Textfelder für die Produktnamen und -preise (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen).
Als nächstes müssen wir die Schaltflächen Produkte aus Versand hinzufügen und Stornieren zur Fußzeile hinzufügen. Ziehen Sie zwei Button-Steuerelemente aus der Toolbox in die Fußzeile der Einfügeschnittstelle, und legen Sie die Buttons-Eigenschaften ID
auf AddProducts
CancelButton
Text
und und auf Produkte aus Versand hinzufügen bzw. Stornieren fest. Legen Sie außerdem die s-Eigenschaft des CancelButton
Steuerelements CausesValidation
auf false
fest.
Schließlich müssen wir ein Label Web-Steuerelement hinzufügen, das Statusmeldungen für die beiden Schnittstellen anzeigt. Wenn ein Benutzer beispielsweise erfolgreich eine neue Produktsendung hinzufügt, möchten wir zur Anzeigeoberfläche zurückkehren und eine Bestätigungsmeldung anzeigen. Wenn der Benutzer jedoch einen Preis für ein neues Produkt angibt, aber den Produktnamen weglässt, müssen wir eine Warnmeldung anzeigen, da das ProductName
Feld erforderlich ist. Da diese Meldung für beide Schnittstellen angezeigt werden muss, platzieren Sie sie oben auf der Seite außerhalb der Panels.
Ziehen Sie ein Label-Web-Steuerelement aus der Toolbox an den oberen Rand der Seite im Designer. Legen Sie die ID
Eigenschaft auf StatusLabel
fest, löschen Sie die Text
Eigenschaft, und legen Sie die Visible
EnableViewState
und-Eigenschaften auf False
fest. Wie wir in früheren Tutorials gesehen haben, können wir durch Festlegen der EnableViewState
Eigenschaft auf False
programmgesteuert die Eigenschaftswerte von Label ändern und sie beim nachfolgenden Postback automatisch auf ihre Standardwerte zurücksetzen. Dies vereinfacht den Code zum Anzeigen einer Statusmeldung als Reaktion auf eine Benutzeraktion, die beim nachfolgenden Postback verschwindet. Legen Sie abschließend die StatusLabel
Eigenschaft des Steuerelements CssClass
auf Warnung fest, was dem Namen einer CSS-Klasse entspricht, die in Styles.css
definiert ist und Text in einer großen, kursiven, fetten, roten Schriftart anzeigt.
Abbildung 11 zeigt den Visual Studio-Designer, nachdem die Bezeichnung hinzugefügt und konfiguriert wurde.
Abbildung 11: Platzieren des StatusLabel
Steuerelements über den beiden Bereichssteuerelementen (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Schritt 3: Wechseln zwischen dem Display und Einfügen von Schnittstellen
Zu diesem Zeitpunkt haben wir das Markup für unsere Anzeige- und Einfügeschnittstellen abgeschlossen, aber es bleiben noch zwei Aufgaben:
- Umschalten zwischen dem Display und Einfügen von Schnittstellen
- Hinzufügen der Produkte in der Sendung zur Datenbank
Derzeit ist die Anzeigeschnittstelle sichtbar, aber die Einfügeschnittstelle ist ausgeblendet. Dies liegt daran, dass die DisplayInterface
Eigenschaft Panel s Visible
auf True
(den Standardwert) festgelegt ist, während die InsertingInterface
Eigenschaft Panel s Visible
auf False
festgelegt ist. Um zwischen den beiden Schnittstellen zu wechseln, müssen wir lediglich den Eigenschaftswert jedes Steuerelements Visible
umschalten.
Wir möchten von der Anzeigeoberfläche zur Einfügeschnittstelle wechseln, wenn auf die Schaltfläche Produktversand verarbeiten geklickt wird. Erstellen Sie daher einen Ereignishandler für dieses Button-Ereignis, der Click
den folgenden Code enthält:
Protected Sub ProcessShipment_Click(sender As Object, e As EventArgs) _
Handles ProcessShipment.Click
DisplayInterface.Visible = False
InsertingInterface.Visible = True
End Sub
Dieser Code blendet einfach das DisplayInterface
Panel aus und zeigt das InsertingInterface
Panel an.
Erstellen Sie als Nächstes Ereignishandler für die Steuerelemente "Produkte aus Sendung hinzufügen" und "Schaltfläche "Abbrechen" in der Einfügeschnittstelle. Wenn auf eine dieser Schaltflächen geklickt wird, müssen wir zur Anzeigeoberfläche zurückkehren. Erstellen Sie Click
Ereignishandler für beide Button-Steuerelemente, sodass sie ReturnToDisplayInterface
aufrufen, eine Methode, die wir gleich hinzufügen werden. Zusätzlich zum Ein- und Ausblenden InsertingInterface
des DisplayInterface
Bereichs muss die ReturnToDisplayInterface
Methode die Websteuerelemente in den Zustand vor der Bearbeitung zurücksetzen. Dazu gehören das Festlegen der DropDownLists-Eigenschaften SelectedIndex
auf 0 und das Löschen der Text
Eigenschaften der TextBox-Steuerelemente.
Hinweis
Überlegen Sie, was passieren könnte, wenn wir die Steuerelemente nicht in den Zustand vor der Bearbeitung zurücksetzen, bevor wir zur Anzeigeoberfläche zurückkehren. Ein Benutzer kann auf die Schaltfläche Produktsendung verarbeiten klicken, die Produkte aus der Sendung eingeben und dann auf Produkte aus Sendung hinzufügen klicken. Dadurch werden die Produkte hinzugefügt und der Benutzer kehrt zur Anzeigeoberfläche zurück. An dieser Stelle möchte der Benutzer möglicherweise eine weitere Sendung hinzufügen. Wenn Sie auf die Schaltfläche Produktversand verarbeiten klicken, kehren sie zur Einfügeschnittstelle zurück, aber die DropDownList-Auswahlen und TextBox-Werte werden weiterhin mit ihren vorherigen Werten aufgefüllt.
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
Beide Click
Ereignishandler rufen einfach die ReturnToDisplayInterface
Methode auf, obwohl wir in Schritt 4 zum Ereignishandler Produkte aus Sendung Click
hinzufügen zurückkehren und Code zum Speichern der Produkte hinzufügen.
ReturnToDisplayInterface
beginnt mit der Rückgabe von Suppliers
Categories
und DropDownLists an ihre ersten Optionen. Die beiden Konstanten firstControlID
und lastControlID
markieren die Indexwerte für das Start- und Endsteuerelement, die bei der Benennung der TextBoxes für den Produktnamen und den Stückpreis in der Einfügeschnittstelle verwendet werden, und werden in den Grenzen der For
Schleife verwendet, die die Text
Eigenschaften der TextBox-Steuerelemente auf eine leere Zeichenfolge zurücksetzt. Schließlich werden die Panel-Eigenschaften Visible
zurückgesetzt, sodass die Einfügeschnittstelle ausgeblendet und die Anzeigeschnittstelle angezeigt wird.
Nehmen Sie sich einen Moment Zeit, um diese Seite in einem Browser zu testen. Wenn Sie die Seite zum ersten Mal besuchen, sollten Sie die Anzeigeoberfläche sehen, wie in Abbildung 5 gezeigt. Klicken Sie auf die Schaltfläche Produktversand bearbeiten. Die Seite wird zurückgesetzt, und Sie sollten nun die Einfügeschnittstelle sehen, wie in Abbildung 12 dargestellt. Wenn Sie auf die Schaltflächen Produkte aus Versand hinzufügen oder Stornieren klicken, kehren Sie zur Anzeigeoberfläche zurück.
Hinweis
Nehmen Sie sich beim Anzeigen der Einfügeschnittstelle einen Moment Zeit, um die CompareValidators für die TextBoxes zum Stückpreis zu testen. Wenn Sie auf die Schaltfläche Produkte aus Sendung hinzufügen mit ungültigen Währungswerten oder Preisen mit einem Wert kleiner als Null klicken, sollte eine clientseitige Meldungswarnung angezeigt werden.
Abbildung 12: Die Einfügeschnittstelle wird angezeigt, nachdem Sie auf die Schaltfläche "Produktversand verarbeiten" geklickt haben (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen).
Schritt 4: Hinzufügen der Produkte
In diesem Tutorial müssen Sie die Produkte nur noch in der Datenbank im Ereignishandler der Schaltfläche "Produkte aus Sendung hinzufügen" Click
speichern. Dies kann erreicht werden, indem Sie für jeden der angegebenen Produktnamen eine ProductsDataTable
Instanz erstellen und hinzufügen ProductsRow
. Sobald diese ProductsRow
s hinzugefügt wurden, rufen wir die ProductsBLL
Methode s der Klasse auf UpdateWithTransaction
und übergeben die ProductsDataTable
. Denken Sie daran, dass die UpdateWithTransaction
Methode, die bereits im Tutorial zum Umschließen von Datenbankänderungen in einer Transaktion erstellt wurde, die ProductsDataTable
an die ProductsTableAdapter
Methode von übergibt.UpdateWithTransaction
Von dort aus wird eine ADO.NET Transaktion gestartet, und der TableAdapter gibt für jede in der DataTable hinzugefügte INSERT
Transaktion eine ProductsRow
Anweisung an die Datenbank aus. Unter der Annahme, dass alle Produkte ohne Fehler hinzugefügt werden, wird für die Transaktion ein Commit ausgeführt, andernfalls wird ein Rollback ausgeführt.
Der Code für den Ereignishandler der Schaltfläche Click
"Produkte aus Sendung hinzufügen" muss ebenfalls eine Fehlerüberprüfung durchführen. Da in der Einfügeschnittstelle keine RequiredFieldValidators verwendet werden, kann ein Benutzer einen Preis für ein Produkt eingeben, ohne dessen Namen zu verwenden. Da der Name des Produkts erforderlich ist, müssen wir den Benutzer warnen und nicht mit den Einfügungen fortfahren, wenn ein solcher Zustand eintritt. Der vollständige Click
Ereignishandlercode lautet:
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
Der Ereignishandler stellt zunächst sicher, dass die Page.IsValid
Eigenschaft den Wert .True
Wenn zurückgegeben wird False
, bedeutet dies, dass einer oder mehrere der CompareValidators ungültige Daten melden. In einem solchen Fall möchten wir nicht versuchen, die eingegebenen Produkte einzufügen, oder wir erhalten eine Ausnahme, wenn wir versuchen, den vom Benutzer eingegebenen Stückpreiswert der ProductsRow
UnitPrice
s-Eigenschaft zuzuweisen.
Als Nächstes wird eine neue ProductsDataTable
Instanz erstellt (products
). Eine For
Schleife wird verwendet, um die TextBoxen für den Produktnamen und den Stückpreis zu durchlaufen, und die Text
Eigenschaften werden in die lokalen Variablen productName
und unitPrice
eingelesen. Wenn der Benutzer einen Wert für den Stückpreis, aber nicht für den entsprechenden Produktnamen eingegeben hat, StatusLabel
wird die Meldung Wenn Sie einen Stückpreis angeben, müssen Sie auch den Namen des Produkts angeben, und der Event-Handler wird beendet.
Wenn ein Produktname angegeben wurde, wird mit der ProductsRow
s-Methode ProductsDataTable
eine neue NewProductsRow
Instanz erstellt. Die Eigenschaft dieser neuen ProductsRow
Instanz wird auf den aktuellen Produktnamen TextBox festgelegt, während die ProductName
SupplierID
und-Eigenschaften den CategoryID
Eigenschaften der DropDownLists im Kopfzeile der Einfügeschnittstelle zugewiesen SelectedValue
werden. Wenn der Benutzer einen Wert für den Preis des Produkts eingegeben hat, wird dieser der ProductsRow
Eigenschaft der Instanz der UnitPrice
Instanz zugewiesen. Andernfalls wird die Eigenschaft nicht zugewiesen, was zu einem NULL
Wert für UnitPrice
in der Datenbank führt. Schließlich werden die Discontinued
UnitsOnOrder
und-Eigenschaften den hartcodierten Werten False
bzw. 0 zugewiesen.
Nachdem der Instanz die Eigenschaften zugewiesen ProductsRow
wurden, wird sie der .ProductsDataTable
Am Ende des For
Loops prüfen wir, ob Produkte hinzugefügt wurden. Es kann ja sein, dass der Nutzer auf "Produkte aus Versand hinzufügen" geklickt hat, bevor er Produktnamen oder Preise eingegeben hat. Wenn mindestens ein Produkt in vorhanden ProductsDataTable
ist, wird die ProductsBLL
Methode der Klasse s UpdateWithTransaction
aufgerufen. Als Nächstes werden die Daten in die ProductsGrid
GridView zurückgebunden, sodass die neu hinzugefügten Produkte in der Anzeigeoberfläche angezeigt werden. Der wird StatusLabel
aktualisiert, um eine Bestätigungsmeldung anzuzeigen, und der ReturnToDisplayInterface
wird aufgerufen, wobei die Einfügeschnittstelle ausgeblendet und die Anzeigeschnittstelle angezeigt wird.
Wenn keine Produkte eingegeben wurden, wird die Einfügeschnittstelle weiterhin angezeigt, aber die Meldung Es wurden keine Produkte hinzugefügt. Bitte geben Sie die Produktnamen und Stückpreise in die Textfelder ein, die angezeigt werden.
Die Abbildungen 13, 14 und 15 zeigen die Einfüge- und Anzeigeschnittstellen in Aktion. In Abbildung 13 hat der Benutzer einen Stückpreiswert ohne entsprechenden Produktnamen eingegeben. Abbildung 14 zeigt die Anzeigeoberfläche, nachdem drei neue Produkte erfolgreich hinzugefügt wurden, während Abbildung 15 zwei der neu hinzugefügten Produkte in der GridView zeigt (das dritte befindet sich auf der vorherigen Seite).
Abbildung 13: Bei der Eingabe eines Stückpreises ist ein Produktname erforderlich (Klicken Sie auf diese Schaltfläche, um das Bild in voller Größe anzuzeigen)
Abbildung 14: Drei neue Gemüsesorten wurden für den Lieferanten Mayumi s hinzugefügt (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Abbildung 15: Die neuen Produkte finden Sie auf der letzten Seite der GridView (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Hinweis
Die in diesem Tutorial verwendete Batcheinfügelogik umschließt die Einfügungen innerhalb des Transaktionsbereichs. Um dies zu überprüfen, führen Sie gezielt einen Fehler auf Datenbankebene ein. Anstatt z. B. die Eigenschaft der ProductsRow
neuen CategoryID
Instanz dem ausgewählten Wert in der Categories
DropDownList zuzuweisen, weisen Sie sie einem Wert wie i * 5
zu. Hier i
ist der Schleifenindexer mit Werten zwischen 1 und 5. Wenn Sie also zwei oder mehr Produkte in der Stapeleinfügung hinzufügen, hat das erste Produkt einen gültigen CategoryID
Wert (5), aber nachfolgende Produkte haben CategoryID
Werte, die nicht mit CategoryID
den Werten in der Categories
Tabelle übereinstimmen. Der Nettoeffekt ist, dass die ersten INSERT
erfolgreich sind, die nachfolgenden jedoch mit einer Verletzung der Fremdschlüsseleinschränkung fehlschlagen. Da es sich bei der Batcheinfügung um eine atomare Komponente handelt, wird für die erste INSERT
ein Rollback ausgeführt, wodurch die Datenbank in den Zustand vor Beginn des Batcheinfügeprozesses zurückversetzt wird.
Zusammenfassung
In diesem und den beiden vorherigen Tutorials haben wir Schnittstellen erstellt, die das Aktualisieren, Löschen und Einfügen von Datenbatches ermöglichen, die alle die Transaktionsunterstützung verwendeten, die wir der Datenzugriffsschicht im Tutorial zum Umschließen von Datenbankänderungen innerhalb einer Transaktion hinzugefügt haben. In bestimmten Szenarien verbessern solche Benutzeroberflächen für die Stapelverarbeitung die Effizienz des Endbenutzers erheblich, indem sie die Anzahl der Klicks, Postbacks und Kontextwechsel zwischen Tastatur und Maus reduzieren und gleichzeitig die Integrität der zugrunde liegenden Daten beibehalten.
Dieses Tutorial vervollständigt unseren Blick auf die Arbeit mit Batchdaten. In der nächsten Reihe von Tutorials wird eine Vielzahl erweiterter Szenarien der Datenzugriffsschicht untersucht, einschließlich der Verwendung gespeicherter Prozeduren in den TableAdapter-Methoden, des Konfigurierens von Einstellungen auf Verbindungs- und Befehlsebene in der DAL, des Verschlüsselns von Verbindungszeichenfolgen und vieles mehr!
Glückliche Programmierung!
Zum Autor
Scott Mitchell, Autor von sieben ASP/ASP.NET Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft Web Technologies zusammen. Scott arbeitet als unabhängiger Berater, Trainer und Schriftsteller. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann bei mitchell@4GuysFromRolla.comerreicht werden.
Besonderer Dank an
Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Die Hauptrezensenten für dieses Tutorial waren Hilton Giesenow und S ren Jacob Lauritsen. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn ja, schicken Sie mir eine Nachricht an mitchell@4GuysFromRolla.com.