Freigeben über


Batch-Einfügen (VB)

von Scott Mitchell

PDF herunterladen

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 ProductNameUnitPrice die in den Textfeldern eingegebenen Werte zugewiesen, während den Werten "und" CategoryIDSupplierID die Werte aus den Dropdown-Listen oben im Formular zugewiesen werden. Discontinued Die UnitsOnOrder und-Werte werden auf die hartcodierten Werte bzwFalse. 0 festgelegt.

Die Schnittstelle zum Batch-Einfügen

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

Ziehen Sie ein Bedienfeld aus der Toolbox auf den Designer

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.

Zeigen Sie die Daten an, die von der GetProducts-Methode der ProductsBLL-Klasse zurückgegeben werden

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)

Legen Sie die Drop-Down Listen in den Tabs UPDATE, INSERT und DELETE auf (Keine) fest.

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, , CategoryNameSupplierName, 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 Falsesetzen. 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.

Die GridView listet die Produkte auf und bietet Sortier- und Paging-Funktionen

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

Die Einfügeschnittstelle besteht aus einer vierspaltigen, Seven-Row Tabelle

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.

Konfigurieren der ObjectDataSource für die Verwendung der GetSuppliers-Methode der SuppliersBLL-Klasse

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.

Zeigen Sie das Datenfeld CompanyName an, und verwenden Sie SupplierID als Wert.

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.

Die Kopfzeile enthält nun die Dropdown-Listen Lieferanten und Kategorien

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, ProductName3usw 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 Currencyfest. 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 Falsefest. 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.

Die Einfügeschnittstelle enthält jetzt Textfelder für die Produktnamen und Preise

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 AddProductsCancelButtonText und und auf Produkte aus Versand hinzufügen bzw. Stornieren fest. Legen Sie außerdem die s-Eigenschaft des CancelButton Steuerelements CausesValidation auf falsefest.

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 StatusLabelfest, löschen Sie die Text Eigenschaft, und legen Sie die VisibleEnableViewState und-Eigenschaften auf Falsefest. 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.

Platzieren Sie das StatusLabel-Steuerelement über den beiden Bereichssteuerelementen

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 Falsefestgelegt 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 ReturnToDisplayInterfaceaufrufen, 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 SuppliersCategories 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.

Die Einfügeschnittstelle wird angezeigt, nachdem Sie auf die Schaltfläche Produktversand verarbeiten geklickt haben

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 ProductsTableAdapterMethode 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 ProductsRowUnitPrice 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 unitPriceeingelesen. 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 ProductNameSupplierID 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 DiscontinuedUnitsOnOrder 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 ProductsDataTableist, 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).

Bei der Eingabe eines Stückpreises ist ein Produktname erforderlich

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)

Drei neue Gemüsesorten gibt es für den Lieferanten Mayumi S

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)

Die neuen Produkte finden Sie auf der letzten Seite der GridView

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 * 5zu. 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.