Durchführen von Batchupdates (VB)
von Scott Mitchell
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 Lernprogramm haben wir untersucht, wie eine DataList auf Elementebene erstellt wird. Wie bei der standardmäßigen bearbeitbaren GridView enthielt jedes Element in der DataList eine Bearbeitungsschaltfläche, die beim Klicken auf das Element bearbeitbar wäre. Die Bearbeitung auf Elementebene eignet sich zwar gut für Daten, die nur gelegentlich aktualisiert werden, aber bestimmte Anwendungsfallszenarien erfordern, dass der Benutzer viele Datensätze bearbeiten kann. Wenn ein Benutzer Dutzende von Datensätzen bearbeiten muss und gezwungen ist, auf "Bearbeiten" zu klicken, seine Änderungen vorzunehmen und auf "Aktualisieren" zu klicken, kann die Anzahl des Klickens ihre Produktivität beeinträchtigen. In solchen Situationen besteht eine bessere Option darin, eine vollständig bearbeitbare DataList bereitzustellen, bei der sich alle zugehörigen Elemente im Bearbeitungsmodus befinden und deren Werte durch Klicken auf eine Schaltfläche "Alle aktualisieren" auf der Seite bearbeitet werden können (siehe Abbildung 1).
Abbildung 1: Jedes Element in einer vollständig bearbeitbaren DataList kann geändert werden (Klicken, um das Bild in voller Größe anzuzeigen)
In diesem Lernprogramm untersuchen wir, wie Sie Benutzern das Aktualisieren von Lieferantenadresseninformationen mithilfe einer vollständig bearbeitbaren DataList ermöglichen.
Schritt 1: Erstellen der bearbeitbaren Benutzeroberfläche in der DataList s ItemTemplate
Im vorherigen Lernprogramm, in dem wir eine standardmäßige, bearbeitbare DataList auf Elementebene erstellen, haben wir zwei Vorlagen verwendet:
ItemTemplate
enthält die schreibgeschützte Benutzeroberfläche (die Bezeichnungswebsteuerelemente zum Anzeigen des Jeweiligen Produktnamens und Preises).EditItemTemplate
enthält die Benutzeroberfläche des Bearbeitungsmodus (die beiden TextBox-Websteuerelemente).
Die DataList-Eigenschaft EditItemIndex
bestimmt, was DataListItem
(falls vorhanden) mithilfe der EditItemTemplate
. Insbesondere wird der DataListItem
Wert, dessen ItemIndex
Wert mit der DataList-Eigenschaft EditItemIndex
übereinstimmt, mithilfe der EditItemTemplate
. Dieses Modell funktioniert gut, wenn jeweils nur ein Element bearbeitet werden kann, aber beim Erstellen einer vollständig bearbeitbaren DataList auseinanderfällt.
Für eine vollständig bearbeitbare DataList möchten wir, dass alle DataListItem
Elemente mithilfe der bearbeitbaren Schnittstelle gerendert werden. Die einfachste Möglichkeit, dies zu erreichen, ist das Definieren der bearbeitbaren Schnittstelle in der ItemTemplate
. Zum Ändern der Adressinformationen der Lieferanten 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 Suppliers
. Wählen Sie aus dem Smarttag "DataList" ein neues ObjectDataSource-Steuerelement mit dem Namen .SuppliersDataSource
Abbildung 2: Erstellen einer neuen ObjectDataSource namens SuppliersDataSource
(Klicken Sie, um das Bild in voller Größe anzuzeigen)
Konfigurieren Sie objectDataSource so, dass Daten mithilfe der SuppliersBLL
Klassenmethode GetSuppliers()
abgerufen werden (siehe Abbildung 3). Wie im vorherigen Lernprogramm arbeiten wir, anstatt die Lieferanteninformationen über ObjectDataSource zu aktualisieren, direkt mit der Geschäftslogikebene zusammen. Legen Sie daher die Dropdownliste auf (Keine) auf der Registerkarte UPDATE fest (siehe Abbildung 4).
Abbildung 3: Abrufen von Lieferanteninformationen mithilfe der GetSuppliers()
Methode (Klicken, um das Bild in voller Größe anzuzeigen)
Abbildung 4: Festlegen der Dropdownliste auf (Keine) auf der Registerkarte "AKTUALISIEREN" (Klicken Sie hier, um das Bild in voller Größe anzuzeigen)
Nach Abschluss des Assistenten generiert Visual Studio automatisch die DataList-Elemente ItemTemplate
, um jedes Datenfeld anzuzeigen, das von der Datenquelle in einem Bezeichnungswebsteuerelement zurückgegeben wird. Wir müssen diese Vorlage so ändern, dass sie stattdessen die Bearbeitungsschnittstelle bereitstellt. Dies ItemTemplate
kann über den Designer mithilfe der Option "Vorlagen bearbeiten" aus dem Smarttag von DataList oder direkt über die deklarative Syntax angepasst werden.
Nehmen Sie sich einen Moment Zeit, um eine Bearbeitungsschnittstelle 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 Lernprogramm muss die DataList in diesem Lernprogramm den Ansichtsstatus aktiviert haben.
In der ItemTemplate
I m using two new CSS classes, SupplierPropertyLabel
and SupplierPropertyValue
, which been added to the Styles.css
class and configured to use the same style settings as the ProductPropertyLabel
and ProductPropertyValue
CSS classes.
.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 in Abbildung 5 dargestellt, zeigt jedes DataList-Element den Lieferantennamen als Text an und verwendet TextBoxes zum Anzeigen der Adresse, des Orts und der Region.
Abbildung 5: Jeder Lieferant in der DataList ist bearbeitbar (Zum Anzeigen des Bilds mit voller Größe klicken)
Schritt 2: Hinzufügen einer Schaltfläche "Alle aktualisieren"
Während jeder Lieferant in Abbildung 5 die Felder "Adresse", "Ort" und "Land/Region" in einem TextBox-Element anzeigt, ist derzeit keine Schaltfläche "Aktualisieren" verfügbar. Anstatt eine Schaltfläche "Aktualisieren" pro Element zu haben, gibt es in der Regel eine einzelne Schaltfläche "Alle aktualisieren" auf der Seite, die alle Datensätze in der DataList aktualisiert. In diesem Lernprogramm fügen wir zwei Schaltflächen "Alle aktualisieren" hinzu – eine am oberen Rand der Seite und eine am unteren Rand (obwohl das Klicken auf eine der Schaltflächen denselben Effekt hat).
Fügen Sie zunächst ein Schaltflächenweb-Steuerelement oberhalb der DataList hinzu, und legen Sie dessen ID
Eigenschaft auf UpdateAll1
. Fügen Sie als Nächstes das zweite Schaltflächen-Websteuerelement unter der DataList hinzu, und legen Sie sie ID
auf UpdateAll2
. Legen Sie die Text
Eigenschaften für die beiden Schaltflächen auf "Alle aktualisieren" fest. Erstellen Sie schließlich Ereignishandler für beide Schaltflächenereignisse Click
. Anstatt die Aktualisierungslogik in jedem der Ereignishandler zu duplizieren, lassen Sie uns diese Logik in eine dritte Methode umgestalten, UpdateAllSupplierAddresses
wobei die Ereignishandler einfach diese dritte Methode aufrufen.
Protected Sub UpdateAll1_Click(sender As Object, e As EventArgs) _
Handles UpdateAll1.Click
UpdateAllSupplierAddresses()
End Sub
Protected Sub UpdateAll2_Click(sender As Object, e As EventArgs) _
Handles UpdateAll2.Click
UpdateAllSupplierAddresses()
End Sub
Private Sub UpdateAllSupplierAddresses()
' TODO: Write code to update _all_ of the supplier addresses in the DataList
End Sub
Abbildung 6 zeigt die Seite, nachdem die Schaltflächen "Alle aktualisieren" hinzugefügt wurden.
Abbildung 6: Zwei Schaltflächen aktualisieren wurden zur Seite hinzugefügt (Klicken, um das Bild in voller Größe anzuzeigen)
Schritt 3: Aktualisieren aller Adressinformationen der Lieferanten
Bei allen DataList-Elementen, die die Bearbeitungsoberfläche anzeigen, und mit dem Hinzufügen der Schaltflächen "Alle aktualisieren", schreibt alles, was weiterhin den Code schreibt, um die Batchaktualisierung durchzuführen. Insbesondere müssen wir die DataList-Elemente durchlaufen und die Methode der SuppliersBLL
UpdateSupplierAddress
Klasse für jede aufrufen.
Auf die Sammlung von DataListItem
Instanzen, die die DataList erstellen, kann über die DataList-EigenschaftItems
zugegriffen werden. Mit einem Verweis auf ein DataListItem
Objekt können wir das entsprechende SupplierID
aus der DataKeys
Auflistung abrufen und programmgesteuert auf die TextBox-Websteuerelemente innerhalb des ItemTemplate
folgenden Codes verweisen:
Private Sub UpdateAllSupplierAddresses()
' Create an instance of the SuppliersBLL class
Dim suppliersAPI As New SuppliersBLL()
' Iterate through the DataList's items
For Each item As DataListItem In Suppliers.Items
' Get the supplierID from the DataKeys collection
Dim supplierID As Integer = Convert.ToInt32(Suppliers.DataKeys(item.ItemIndex))
' Read in the user-entered values
Dim address As TextBox = CType(item.FindControl("Address"), TextBox)
Dim city As TextBox = CType(item.FindControl("City"), TextBox)
Dim country As TextBox = CType(item.FindControl("Country"), TextBox)
Dim addressValue As String = Nothing, _
cityValue As String = Nothing, _
countryValue As String = Nothing
If address.Text.Trim().Length > 0 Then
addressValue = address.Text.Trim()
End If
If city.Text.Trim().Length > 0 Then
cityValue = city.Text.Trim()
End If
If country.Text.Trim().Length > 0 Then
countryValue = country.Text.Trim()
End If
' Call the SuppliersBLL class's UpdateSupplierAddress method
suppliersAPI.UpdateSupplierAddress _
(supplierID, addressValue, cityValue, countryValue)
Next
End Sub
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 Methode der SuppliersBLL
Klasse 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
( UpdateSupplierAddress
anstelle einer leeren Zeichenfolge), der zu einer Datenbank NULL
für die zugrunde liegenden Datensatzfelder führt.
Hinweis
Als Erweiterung möchten Sie der Seite möglicherweise ein Statusbezeichnung-Websteuerelement hinzufügen, das nach der Batchaktualisierung eine Bestätigungsmeldung bereitstellt.
Aktualisieren nur der Adressen, die geändert wurden
Der für dieses Lernprogramm verwendete Batchaktualisierungsalgorithmus ruft die UpdateSupplierAddress
Methode für jeden Lieferanten in der DataList auf, unabhängig davon, ob ihre Adressinformationen geändert wurden. Während solche Blindupdates in der Regel 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, für jeden Lieferanten im System ein neuer Überwachungsdatensatz erstellt, unabhängig davon, ob der Benutzer Änderungen vorgenommen hat.
Die ADO.NET DataTable- und DataAdapter-Klassen sind so konzipiert, dass Batchaktualisierungen unterstützt werden, bei denen nur geänderte, gelöschte und neue Datensätze zu einer beliebigen Datenbankkommunikation führen. Jede Zeile in der DataTable weist eine RowState
Eigenschaft auf, die angibt, ob die Zeile der DataTable hinzugefügt, daraus gelöscht, geändert oder unverändert bleibt. Wenn eine DataTable anfangs 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 durch erstes Lesen im Datensatz des einzelnen Lieferanten in einen SuppliersDataTable
und legen dann die Address
Werte City
und Country
Spaltenwerte mithilfe des folgenden Codes fest:
Public Function UpdateSupplierAddress _
(supplierID As Integer, address As String, city As String, country As String) _
As Boolean
Dim suppliers As Northwind.SuppliersDataTable = _
Adapter.GetSupplierBySupplierID(supplierID)
If suppliers.Count = 0 Then
' no matching record found, return false
Return False
Else
Dim supplier As Northwind.SuppliersRow = suppliers(0)
If address Is Nothing Then
supplier.SetAddressNull()
Else
supplier.Address = address
End If
If city Is Nothing Then
supplier.SetCityNull()
Else
supplier.City = city
End If
If country Is Nothing Then
supplier.SetCountryNull()
Else
supplier.Country = country
End If
' Update the supplier Address-related information
Dim rowsAffected As Integer = Adapter.Update(supplier)
' Return true if precisely one row was updated, otherwise false
Return rowsAffected = 1
End If
End Function
Dieser Code weist den übergebenen Adress-, Orts- und Länder-/Regionswerten naiv die Werte unabhängig SuppliersDataTable
davon zuSuppliersRow
, ob sich die Werte geändert haben. Diese Änderungen bewirken, dass die SuppliersRow
Eigenschaft s RowState
als geändert markiert wird. Wenn die Data Access Layer-Methode Update
aufgerufen wird, sieht sie, dass die SupplierRow
Änderung erfolgt ist und sendet daher einen UPDATE
Befehl an die Datenbank.
Stellen Sie sich jedoch vor, dass wir dieser Methode Code hinzugefügt haben, um nur die übergebenen Adress-, Orts- und Länder-/Regionswerte zuzuweisen, wenn sie sich von den SuppliersRow
vorhandenen Werten unterscheiden. Wenn die Adresse, die Stadt und die Region mit den vorhandenen Daten identisch sind, werden keine Änderungen vorgenommen, und die SupplierRow
Daten RowState
werden unverändert markiert. Das Nettoergebnis ist, dass beim Aufrufen der DAL-Methode Update
kein Datenbankaufruf erfolgt, da die SuppliersRow
Methode nicht geändert wurde.
Um diese Änderung zu erlassen, ersetzen Sie die Anweisungen, die blind die übergebenen Adress-, Orts- und Länder-/Regionswerte durch den folgenden Code zuweisen:
' Only assign the values to the SupplierRow's column values if they differ
If address Is Nothing AndAlso Not supplier.IsAddressNull() Then
supplier.SetAddressNull()
ElseIf (address IsNot Nothing AndAlso supplier.IsAddressNull) _
OrElse (Not supplier.IsAddressNull() AndAlso _
String.Compare(supplier.Address, address) <> 0) Then
supplier.Address = address
End If
If city Is Nothing AndAlso Not supplier.IsCityNull() Then
supplier.SetCityNull()
ElseIf (city IsNot Nothing AndAlso supplier.IsCityNull) _
OrElse (Not supplier.IsCityNull() AndAlso _
String.Compare(supplier.City, city) <> 0) Then
supplier.City = city
End If
If country Is Nothing AndAlso Not supplier.IsCountryNull() Then
supplier.SetCountryNull()
ElseIf (country IsNot Nothing AndAlso supplier.IsCountryNull) _
OrElse (Not supplier.IsCountryNull() AndAlso _
String.Compare(supplier.Country, country) <> 0) Then
supplier.Country = country
End If
Mit diesem hinzugefügten Code sendet die DAL-Methode Update
eine UPDATE
Anweisung 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. Wenn keines vorhanden ist, umgehen Sie einfach den Aufruf der DAL s-Methode Update
. Dieser Ansatz funktioniert gut, wenn Sie die direkte DB-Methode verwenden, da die DIREKTE DB-Methode keine Instanz übergeben SuppliersRow
wird, deren RowState
Überprüfung durchgeführt werden kann, um festzustellen, ob ein Datenbankaufruf tatsächlich benötigt wird.
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 vorliegen, wird ein weiterer Aufruf der Datenbank vorgenommen, um die Tabellenzeile zu aktualisieren. Dieser Workflow kann optimiert werden, indem eine UpdateSupplierAddress
Methodenüberladung erstellt wird, die eine EmployeesDataTable
Instanz akzeptiert, die alle Änderungen von der BatchUpdate.aspx
Seite enthält. Anschließend könnte die Datenbank einen Aufruf ausführen, um alle Datensätze aus der Suppliers
Tabelle abzurufen. Die beiden Resultsets können dann aufgezählt werden, und nur die Datensätze, in denen Änderungen vorgenommen wurden, konnten aktualisiert werden.
Zusammenfassung
In diesem Lernprogramm haben wir erfahren, wie Sie eine vollständig bearbeitbare DataList erstellen, sodass ein Benutzer die Adressinformationen für mehrere Lieferanten schnell ändern kann. Wir haben begonnen, die Bearbeitungsschnittstelle ein TextBox-Websteuerelement für die Adressen, Ort und Länder/Region des Lieferanten in den DataList s ItemTemplate
zu definieren. Als Nächstes haben wir oben und unterhalb der DataList "Alle aktualisieren"-Schaltflächen hinzugefügt. Nachdem ein Benutzer seine Änderungen vorgenommen und auf eine der Schaltflächen "Alle aktualisieren" geklickt hat, werden die DataListItem
Elemente aufgezählt, und ein Aufruf der Methode der SuppliersBLL
Klasse UpdateSupplierAddress
erfolgt.
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 über mitchell@4GuysFromRolla.com seinen Blog erreicht werden, der unter .http://ScottOnWriting.NET
Besonderer Dank an
Diese Lernprogrammreihe wurde von vielen hilfreichen Prüfern überprüft. Leitende Prüfer für dieses Lernprogramm waren Zack Jones und Ken Pespisa. Möchten Sie meine bevorstehenden MSDN-Artikel überprüfen? Wenn dies der Fall ist, legen Sie mir eine Zeile bei mitchell@4GuysFromRolla.com.