Share via


Durchführen von Batchupdates (C#)

von Scott Mitchell

PDF herunterladen

Erfahren Sie, wie Sie eine vollständig bearbeitbare DataList erstellen, in der sich alle zugehörigen Elemente im Bearbeitungsmodus befinden und deren Werte gespeichert werden können, indem Sie auf der Seite auf eine Schaltfläche "Alle aktualisieren" klicken.

Einführung

Im vorherigen Tutorial haben wir untersucht, wie eine DataList auf Elementebene erstellt wird. Wie die standardmäßig bearbeitbare GridView enthielt jedes Element in der DataList eine Schaltfläche Bearbeiten, die das Element beim Klicken bearbeitbar macht. Während diese Bearbeitung auf Elementebene gut für Daten funktioniert, die nur gelegentlich aktualisiert werden, erfordern bestimmte Anwendungsfälle, dass der Benutzer viele Datensätze bearbeitet. Wenn ein Benutzer Dutzende von Datensätzen bearbeiten muss und gezwungen ist, auf Bearbeiten zu klicken, seine Änderungen vorzunehmen und für jeden Einzelnen auf Aktualisieren zu klicken, kann die Menge des Klickens seine Produktivität beeinträchtigen. In solchen Situationen besteht eine bessere Option darin, eine vollständig bearbeitbare DataList bereitzustellen, bei der sich alle Elemente im Bearbeitungsmodus befinden und deren Werte durch Klicken auf die Schaltfläche Alle aktualisieren auf der Seite bearbeitet werden können (siehe Abbildung 1).

Jedes Element in einer vollständig bearbeitbaren DataList kann geändert werden.

Abbildung 1: Jedes Element in einer vollständig bearbeitbaren DataList kann geändert werden (Klicken Sie, um das bild in voller Größe anzuzeigen)

In diesem Tutorial wird untersucht, wie Benutzern das Aktualisieren von Adressinformationen von Lieferanten mithilfe einer vollständig bearbeitbaren DataList ermöglicht wird.

Schritt 1: Erstellen der bearbeitbaren Benutzeroberfläche in der DataList-Elementvorlage

Im vorherigen Tutorial, in dem eine bearbeitbare Standard-DataList auf Elementebene erstellt wurde, haben wir zwei Vorlagen verwendet:

  • ItemTemplate enthält die schreibgeschützte Benutzeroberfläche (die Label-Websteuerelemente zum Anzeigen von Produktnamen und -preisen).
  • EditItemTemplate enthält die Benutzeroberfläche im Bearbeitungsmodus (die beiden TextBox-Websteuerelemente).

Die DataList-Eigenschaft EditItemIndex diktiert, was DataListItem (falls vorhanden) mit EditItemTemplategerendert wird. Insbesondere wird der DataListItem , dessen ItemIndex Wert mit der DataList-Eigenschaft EditItemIndex übereinstimmt, mithilfe von EditItemTemplategerendert. Dieses Modell funktioniert gut, wenn nur ein Element gleichzeitig bearbeitet werden kann, fällt aber beim Erstellen einer vollständig bearbeitbaren DataList auseinander.

Für eine vollständig bearbeitbare DataList sollen alle s mithilfe der DataListItem bearbeitbaren Schnittstelle gerendert werden. Die einfachste Möglichkeit, dies zu erreichen, besteht darin, die bearbeitbare Schnittstelle in zu ItemTemplatedefinieren. Zum Ändern der Lieferantenadresseninformationen enthält die bearbeitbare Schnittstelle den Lieferantennamen als Text und dann TextBoxes für die Werte "Adresse", "Ort" und "Land/Region".

Öffnen Sie zunächst die BatchUpdate.aspx Seite, fügen Sie ein DataList-Steuerelement hinzu, und legen Sie dessen ID Eigenschaft auf fest Suppliers. Wählen Sie im Smarttag dataList ein neues ObjectDataSource-Steuerelement mit dem Namen SuppliersDataSourcehinzu.

Erstellen einer neuen ObjectDataSource mit dem Namen SuppliersDataSource

Abbildung 2: Erstellen eines neuen ObjectDataSource-Namens SuppliersDataSource (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Konfigurieren Sie objectDataSource zum Abrufen von Daten mithilfe der SuppliersBLL Methode der Klasse s GetSuppliers() (siehe Abbildung 3). Wie im vorherigen Tutorial arbeiten wir nicht mit den Lieferanteninformationen über die ObjectDataSource, sondern direkt mit der Geschäftslogikebene zusammen. Legen Sie daher die Dropdownliste auf der Registerkarte UPDATE auf (Keine) fest (siehe Abbildung 4).

Abrufen von Lieferanteninformationen mithilfe der GetSuppliers()-Methode

Abbildung 3: Abrufen von Lieferanteninformationen mithilfe der GetSuppliers() -Methode (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Legen Sie die Drop-Down Liste auf der Registerkarte UPDATE auf (Keine) fest.

Abbildung 4: Legen Sie die Drop-Down Liste auf der Registerkarte UPDATE auf (Keine) fest (Klicken Sie, um das bild in voller Größe anzuzeigen)

Nach Abschluss des Assistenten generiert Visual Studio automatisch die DataList s ItemTemplate , um jedes von der Datenquelle zurückgegebene Datenfeld in einem Label-Websteuerelement anzuzeigen. Wir müssen diese Vorlage so ändern, dass sie stattdessen die Bearbeitungsschnittstelle bereitstellt. Die ItemTemplate kann über die Designer mithilfe der Option Vorlagen bearbeiten über das Smarttag des DataList-Smarttags oder direkt über die deklarative Syntax angepasst werden.

Nehmen Sie sich einen Moment Zeit, um eine Bearbeitungsoberfläche zu erstellen, die den Namen des Lieferanten als Text anzeigt, aber TextBoxes für die Adress-, Orts- und Länder-/Regionswerte des Lieferanten enthält. Nachdem Sie diese Änderungen vorgenommen haben, sollte die deklarative Syntax Ihrer Seite wie folgt aussehen:

<asp:DataList ID="Suppliers" runat="server" DataKeyField="SupplierID"
    DataSourceID="SuppliersDataSource">
    <ItemTemplate>
        <h4><asp:Label ID="CompanyNameLabel" runat="server"
            Text='<%# Eval("CompanyName") %>' /></h4>
        <table border="0">
            <tr>
                <td class="SupplierPropertyLabel">Address:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Address" runat="server"
                        Text='<%# Eval("Address") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">City:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="City" runat="server"
                        Text='<%# Eval("City") %>' />
                </td>
            </tr>
            <tr>
                <td class="SupplierPropertyLabel">Country:</td>
                <td class="SupplierPropertyValue">
                    <asp:TextBox ID="Country" runat="server"
                        Text='<%# Eval("Country") %>' />
                </td>
            </tr>
        </table>
        <br />
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="SuppliersDataSource" runat="server"
    OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>

Hinweis

Wie im vorherigen Tutorial muss auch für DataList in diesem Tutorial der Ansichtszustand aktiviert sein.

ItemTemplate Ich verwende zwei neue CSS-Klassen und SupplierPropertyValue, die der Styles.css -Klasse hinzugefügt und so konfiguriert wurden, SupplierPropertyLabel dass sie dieselben Stileinstellungen wie die ProductPropertyLabel CSS-Klassen und ProductPropertyValue verwenden.

.ProductPropertyLabel, .SupplierPropertyLabel
{
    font-weight: bold;
    text-align: right;
}
.ProductPropertyValue, .SupplierPropertyValue
{
    padding-right: 35px;
}

Nachdem Sie diese Änderungen vorgenommen haben, besuchen Sie diese Seite über einen Browser. Wie Abbildung 5 zeigt, zeigt jedes DataList-Element den Lieferantennamen als Text an und verwendet TextBoxes, um die Adresse, den Ort und das Land/die Region anzuzeigen.

Jeder Lieferant in der DataList kann bearbeitet werden.

Abbildung 5: Jeder Lieferant in der DataList ist bearbeitbar (Klicken Sie hier, um das bild in voller Größe anzuzeigen)

Schritt 2: Hinzufügen einer Schaltfläche "Alle aktualisieren"

Während für jeden Lieferanten in Abbildung 5 die Felder Adresse, Ort und Land/Region in einem Textfeld angezeigt werden, ist derzeit keine Schaltfläche Aktualisieren verfügbar. Anstelle einer Schaltfläche Aktualisieren pro Element gibt es bei vollständig bearbeitbaren DataLists in der Regel eine einzelne Schaltfläche Alle aktualisieren auf der Seite, die beim Klicken alle Datensätze in der DataList aktualisiert. In diesem Tutorial fügen Sie zwei Schaltflächen Alle aktualisieren hinzu– eine oben auf der Seite und eine am unteren Rand (obwohl das Klicken auf eine der schaltflächen denselben Effekt hat).

Beginnen Sie mit dem Hinzufügen eines Button-Websteuerelements über der DataList, und legen Sie dessen ID Eigenschaft auf fest UpdateAll1. Fügen Sie als Nächstes das zweite Button-Websteuerelement unter der DataList hinzu, und legen Sie es ID auf fest UpdateAll2. Legen Sie die Text Eigenschaften für die beiden Schaltflächen auf Alle aktualisieren fest. Erstellen Sie schließlich Ereignishandler für beide Buttons-Ereignisse Click . Anstatt die Updatelogik in jedem der Ereignishandler zu duplizieren, lassen Sie diese Logik in eine dritte Methode umgestalten, UpdateAllSupplierAddresseswobei die Ereignishandler einfach diese dritte Methode aufrufen.

protected void UpdateAll1_Click(object sender, EventArgs e)
{
    UpdateAllSupplierAddresses();
}
protected void UpdateAll2_Click(object sender, EventArgs e)
{
    UpdateAllSupplierAddresses();
}
private void UpdateAllSupplierAddresses()
{
    // TODO: Write code to update _all_ of the supplier addresses in the DataList
}

Abbildung 6 zeigt die Seite, nachdem die Schaltflächen Alle aktualisieren hinzugefügt wurden.

Der Seite wurden zwei Schaltflächen

Abbildung 6: Zwei Aktualisierungsschaltflächen wurden der Seite hinzugefügt (Klicken Sie, um das Bild in voller Größe anzuzeigen)

Schritt 3: Aktualisieren aller Adressinformationen von Lieferanten

Da alle DataList-Elemente die Bearbeitungsoberfläche anzeigen und die Schaltflächen Alle aktualisieren hinzugefügt werden, bleibt nur noch das Schreiben des Codes zum Ausführen der Batchaktualisierung. Insbesondere müssen wir die DataList-Elemente durchschleifen und die Methode s UpdateSupplierAddress der SuppliersBLL Klasse für jedes aufrufen.

Auf die Sammlung von DataListItem Instanzen, die die DataList erstellen, kann über die DataList-Eigenschaft Itemszugegriffen werden. Mit einem Verweis auf ein DataListItemkönnen wir das entsprechende SupplierID aus der DataKeys Auflistung abrufen und programmgesteuert auf die TextBox-Websteuerelemente innerhalb von ItemTemplate verweisen, wie der folgende Code veranschaulicht:

private void UpdateAllSupplierAddresses()
{
    // Create an instance of the SuppliersBLL class
    SuppliersBLL suppliersAPI = new SuppliersBLL();
    // Iterate through the DataList's items
    foreach (DataListItem item in Suppliers.Items)
    {
        // Get the supplierID from the DataKeys collection
        int supplierID = Convert.ToInt32(Suppliers.DataKeys[item.ItemIndex]);
        // Read in the user-entered values
        TextBox address = (TextBox)item.FindControl("Address");
        TextBox city = (TextBox)item.FindControl("City");
        TextBox country = (TextBox)item.FindControl("Country");
        string addressValue = null, cityValue = null, countryValue = null;
        if (address.Text.Trim().Length > 0)
            addressValue = address.Text.Trim();
        if (city.Text.Trim().Length > 0)
              cityValue = city.Text.Trim();
        if (country.Text.Trim().Length > 0)
            countryValue = country.Text.Trim();
        // Call the SuppliersBLL class's UpdateSupplierAddress method
        suppliersAPI.UpdateSupplierAddress
            (supplierID, addressValue, cityValue, countryValue);
    }
}

Wenn der Benutzer auf eine der Schaltflächen Alle aktualisieren klickt, durchläuft die UpdateAllSupplierAddresses -Methode jede DataListItem in der Suppliers DataList und ruft die SuppliersBLL Klasse s-Methode UpdateSupplierAddress auf, wobei die entsprechenden Werte übergeben werden. Ein nicht eingegebener Wert für Adress-, Orts- oder Länder-/Regionsdurchläufe ist ein Wert von Nothing von UpdateSupplierAddress (anstelle einer leeren Zeichenfolge), was zu einer Datenbank NULL für die Felder des zugrunde liegenden Datensatzes führt.

Hinweis

Als Erweiterung können Sie der Seite ein status Label-Websteuerelement hinzufügen, das eine Bestätigungsmeldung bereitstellt, nachdem das Batchupdate ausgeführt wurde.

Aktualisieren nur der Adressen, die geändert wurden

Der für dieses Tutorial verwendete Batchupdatealgorithmus ruft die UpdateSupplierAddress Methode für jeden Lieferanten in der DataList auf, unabhängig davon, ob seine Adressinformationen geändert wurden. Während solche blinden Updates normalerweise kein Leistungsproblem sind, können sie zu überflüssigen Datensätzen führen, wenn Sie Änderungen an der Datenbanktabelle überwachen. Wenn Sie beispielsweise Trigger verwenden, um alle UPDATE s in der Suppliers Tabelle in einer Überwachungstabelle aufzuzeichnen, wird jedes Mal, wenn ein Benutzer auf die Schaltfläche Alle aktualisieren klickt, ein neuer Überwachungsdatensatz für jeden Lieferanten im System erstellt, unabhängig davon, ob der Benutzer Änderungen vorgenommen hat.

Die ADO.NET DataTable- und DataAdapter-Klassen sind so konzipiert, dass sie Batchupdates unterstützen, bei denen nur geänderte, gelöschte und neue Datensätze zu einer Datenbankkommunikation führen. Jede Zeile in der DataTable verfügt über eine RowState Eigenschaft , die angibt, ob die Zeile der DataTable hinzugefügt, gelöscht, geändert wurde oder unverändert bleibt. Wenn eine DataTable anfänglich aufgefüllt wird, werden alle Zeilen unverändert markiert. Wenn Sie den Wert einer der Zeilenspalten ändern, wird die Zeile als geändert markiert.

In der SuppliersBLL Klasse aktualisieren wir die angegebenen Adressinformationen des Lieferanten, indem wir zuerst den einzelnen Lieferantendatensatz in einen SuppliersDataTable lesen und dann die AddressSpaltenwerte , Cityund Country mit dem folgenden Code festlegen:

public bool UpdateSupplierAddress
    (int supplierID, string address, string city, string country)
{
    Northwind.SuppliersDataTable suppliers =
        Adapter.GetSupplierBySupplierID(supplierID);
    if (suppliers.Count == 0)
        // no matching record found, return false
        return false;
    else
    {
        Northwind.SuppliersRow supplier = suppliers[0];
        if (address == null)
            supplier.SetAddressNull();
        else
            supplier.Address = address;
        if (city == null)
            supplier.SetCityNull();
        else
            supplier.City = city;
        if (country == null)
            supplier.SetCountryNull();
        else
            supplier.Country = country;
        // Update the supplier Address-related information
        int rowsAffected = Adapter.Update(supplier);
        // Return true if precisely one row was updated,
        // otherwise false
        return rowsAffected == 1;
    }
}

Dieser Code weist naiv die übergebenen Adress-, Orts- und Länder-/Regionswerte dem SuppliersRow in SuppliersDataTable zu, unabhängig davon, ob sich die Werte geändert haben oder nicht. Diese Änderungen führen dazu, dass die SuppliersRow s-Eigenschaft RowState als geändert markiert wird. Wenn die Data Access Layer-Methode Update aufgerufen wird, erkennt sie, dass die SupplierRow geändert wurde, und sendet daher einen UPDATE Befehl an die Datenbank.

Stellen Sie sich jedoch vor, wir haben dieser Methode Code hinzugefügt, um nur die übergebenen Werte für Adresse, Ort und Land/Region zuzuweisen, wenn sie sich von den SuppliersRow vorhandenen Werten unterscheiden. Wenn Adresse, Ort und Land/Region mit den vorhandenen Daten identisch sind, werden keine Änderungen vorgenommen, und die SupplierRow s RowState werden als unverändert markiert. Das Nettoergebnis ist, dass beim Aufruf der DAL-Methode Update kein Datenbankaufruf erfolgt, da der SuppliersRow nicht geändert wurde.

Um diese Änderung zu erzwingen, ersetzen Sie die Anweisungen, die die übergebenen Werte für Adresse, Ort und Land/Region blind zuweisen, durch den folgenden Code:

// Only assign the values to the SupplierRow's column values if they differ
if (address == null && !supplier.IsAddressNull())
    supplier.SetAddressNull();
else if ((address != null && supplier.IsAddressNull()) ||
         (!supplier.IsAddressNull() &&
         string.Compare(supplier.Address, address) != 0))
    supplier.Address = address;
if (city == null && !supplier.IsCityNull())
    supplier.SetCityNull();
else if ((city != null && supplier.IsCityNull()) ||
         (!supplier.IsCityNull() && string.Compare(supplier.City, city) != 0))
    supplier.City = city;
if (country == null && !supplier.IsCountryNull())
    supplier.SetCountryNull();
else if ((country != null && supplier.IsCountryNull()) ||
         (!supplier.IsCountryNull() &&
         string.Compare(supplier.Country, country) != 0))
    supplier.Country = country;

Mit diesem hinzugefügten Code sendet die DAL-Methode Update eine UPDATE Anweisung an die Datenbank nur für die Datensätze, deren adressbezogene Werte geändert wurden.

Alternativ können wir nachverfolgen, ob es Unterschiede zwischen den übergebenen Adressfeldern und den Datenbankdaten gibt, und, falls keine vorhanden sind, einfach den Aufruf der DAL-Methode Update umgehen. Dieser Ansatz funktioniert gut, wenn Sie die direkte DB-Methode verwenden, da die direkte DB-Methode keine instance übergeben SuppliersRow wird, deren RowState Überprüfung überprüft werden kann, ob ein Datenbankaufruf tatsächlich erforderlich ist.

Hinweis

Jedes Mal, wenn die UpdateSupplierAddress Methode aufgerufen wird, wird ein Aufruf der Datenbank ausgeführt, um Informationen zum aktualisierten Datensatz abzurufen. Wenn dann Änderungen an den Daten vorgenommen werden, wird ein weiterer Aufruf der Datenbank ausgeführt, um die Tabellenzeile zu aktualisieren. Dieser Workflow kann optimiert werden, indem eine UpdateSupplierAddress Methodenüberladung erstellt wird, die eine EmployeesDataTable instance akzeptiert, die alle Änderungen von der BatchUpdate.aspx Seite enthält. Anschließend könnte sie einen Aufruf der Datenbank ausführen, um alle Datensätze aus der Suppliers Tabelle abzurufen. Die beiden Resultsets könnten dann aufgelistet werden, und nur die Datensätze, in denen Änderungen aufgetreten sind, konnten aktualisiert werden.

Zusammenfassung

In diesem Tutorial haben wir erfahren, wie Sie eine vollständig bearbeitbare DataList erstellen, die es einem Benutzer ermöglicht, die Adressinformationen für mehrere Lieferanten schnell zu ändern. Zunächst wurde die Bearbeitungsschnittstelle für ein TextBox-Websteuerelement für die Adress-, Orts- und Länder-/Regionswerte des Lieferanten in der DataList definiert ItemTemplate. Als Nächstes haben wir die Schaltflächen Alle aktualisieren oberhalb und unterhalb der DataList hinzugefügt. Nachdem ein Benutzer seine Änderungen vorgenommen und auf eine der Schaltflächen Alle aktualisieren geklickt hat, werden die DataListItem s aufgelistet, und es wird ein Aufruf der Methode der SuppliersBLL Klasse s UpdateSupplierAddress ausgeführt.

Viel Spaß beim Programmieren!

Zum Autor

Scott Mitchell, Autor von sieben ASP/ASP.NET-Büchern und Gründer von 4GuysFromRolla.com, arbeitet seit 1998 mit Microsoft-Webtechnologien. Scott arbeitet als unabhängiger Berater, Trainer und Autor. Sein neuestes Buch ist Sams Teach Yourself ASP.NET 2.0 in 24 Stunden. Er kann unter mitchell@4GuysFromRolla.comoder über seinen Blog erreicht werden, der unter http://ScottOnWriting.NETzu finden ist.

Besonderen Dank an

Diese Tutorialreihe wurde von vielen hilfreichen Prüfern überprüft. Hauptprüfer für dieses Tutorial waren Zack Jones und Ken Pespisa. Möchten Sie meine anstehenden MSDN-Artikel lesen? Wenn dies der Fall ist, legen Sie eine Zeile unter abmitchell@4GuysFromRolla.com.