26.6 Suchen und Filtern
Wie Sie ein DataSet füllen und die Daten darin ändern können, haben Sie auf den letzten Seiten erfahren. Nun wollen wir nach Datenzeilen in einer DataTable suchen und den Tabelleninhalt nach einem selbst definierten Kriterium filtern. Dazu dienen folgende Methoden:
- Find
- Select
26.6.1 Find
Die Methode Find sucht nach einer Datenzeile basierend auf ihrem Primärschlüsselwert. Das setzt voraus, dass die entsprechende Spalte in der zu durchsuchenden Tabelle auch als Primärschlüsselspalte in der DataTable gekennzeichnet ist. Find erreichen Sie über die Eigenschaft Rows der DataTable, die vom Typ DataRowCollection ist.
Da Primärschlüsselwerte immer eindeutig sind, gibt die Methode immer die Referenz auf exakt eine gefundene Zeile zurück oder Nothing, wenn keine Zeile gefunden wird.
'...\ADO\DataSet\Find.vb |
Option Strict On Imports System.Data.Common, System.Data.SqlClient Namespace ADO Module Find Sub Test() Dim conn As DbConnection = New SqlConnection() conn.ConnectionString = "Data Source=(local);" & _ "Initial Catalog=Northwind;Integrated Security=sspi" Dim cmd As DbCommand = New SqlCommand() cmd.CommandText = "SELECT * FROM Orders" cmd.Connection = conn Dim ds As New DataSet() Dim da As DbDataAdapter = New SqlDataAdapter() da.SelectCommand = cmd da.Fill(ds) ' Primärschlüsselspalte festlegen Dim table As DataTable = ds.Tables(0) table.PrimaryKey = New DataColumn() {ds.Tables(0).Columns(0)} Dim row As DataRow = table.Rows.Find(10260) If row IsNot Nothing Then For Each col As DataColumn In table.Columns Console.WriteLine("{0,-15}{1}", col.ColumnName, row(col)) Next Else Console.WriteLine("Keine Datenzeile gefunden.") End If Console.ReadLine() End Sub End Module End Namespace
Der Primärschlüssel einer Tabelle kann aus mehreren Spalten bestehen. Das trifft beispielsweise auf die Tabelle Order Details der Northwind-Datenbank zu. Um in einer Tabelle mit kombiniertem Primärschlüssel nach einer Datenzeile zu suchen, übergeben Sie der Find-Methode ein DataColumn-Array, in dem alle Spalten des Primärschlüssels angegeben sind:
table.PrimaryKey = New DataColumn() { _ table.Columns("OrderID"), table.Columns("ProductID") } Dim komPS() As Object = New Object() {10249, 51} Dim row As DataRow = table.Rows.Find(komPS)
26.6.2 Select
Öfter als die Suche nach einem Primärschlüsselwert kommt die Suche nach allgemeineren Kriterien vor, analog zu einer SQL-SELECT-Abfrage mit einer WHERE-Klausel, die die von der Datenbank bezogenen Datensätze filtert.
Mit der Methode Select eines DataTable-Objekts lassen sich die gewünschten Auswahlkriterien auch auf eine lokale Datensatzliste anwenden. Alle Überladungen der Methode liefern ein DataRow-Array als Ergebnis.
Angenommen, Sie interessieren sich für alle Artikel der Tabelle Products, von denen weniger als 50 im Lager vorhanden sind und deren Preis kleiner als 20 ist. Als SQL-Statement würden Sie das so formulieren:
SELECT * FROM Products WHERE UnitsInStock < 50 AND UnitPrice < 20
Um nach demselben Kriterium eine DataTable zu filtern, übergeben Sie der Select-Methode die WHERE-Klausel als String, aber ohne das WHERE-Statement selbst:
'...\ADO\DataSet\Select.vb |
Option Strict On
Imports System.Data.Common, System.Data.SqlClient
Namespace ADO
Module Select
Sub Test()
Dim conn As DbConnection = New SqlConnection()
conn.ConnectionString = "Data Source=(local);" & _
"Initial Catalog=Northwind;Integrated Security=sspi"
Dim cmd As DbCommand = New SqlCommand()
cmd.CommandText = "SELECT * FROM Products"
cmd.Connection = conn
Dim ds As New DataSet()
Dim da As DbDataAdapter = New SqlDataAdapter()
da.SelectCommand = cmd
da.Fill(ds)
Dim tbl As DataTable = ds.Tables(0)
' Datenzeilen filtern
Dim rows() As DataRow = _
tbl.Select("UnitsInStock < 50 AND UnitPrice < 20")
For Each row As DataRow In rows
Console.WriteLine("{0,-40}{1,-10}{2}", _
row("ProductName"), row("UnitPrice"), row("UnitsInStock"))
Next
Console.ReadLine()
End Sub
End Module
End Namespace
Besonderheiten des Filterkriteriums
Möchten Sie ein Kriterium formulieren, das einen Platzhalter beschreibt, können Sie in Kombination mit dem SQL-LIKE-Operator entweder das Zeichen »%« oder »*« angeben, zum Beispiel um in der Tabelle Products nach allen Artikeln zu suchen, deren Artikelbezeichner mit dem Buchstaben »C« anfängt:
Dim rows() As DataRow = tbl.Select("ProductName LIKE 'C*'")
Dim rows() As DataRow = tbl.Select("ProductName LIKE 'C%'")
Datumsangaben werden in #-Zeichen eingeschlossen: zuerst der Monat, dann der Tag, am Ende das Jahr. Alle Angaben werden durch einen Schrägstrich voneinander getrennt, zum Beispiel um alle Bestellungen zu erhalten, die am 4. Juli 1996 eingegangen sind:
Dim rows() As DataRow = tbl.Select("OrderDate = #7/4/1996#")
Sortieren mit Select
Eine Überladung der Select-Methode sortiert die Datenzeilen einer DataTable außerdem. Im ersten Argument wird das Auswahlkriterium angegeben, im zweiten das der Sortierung. Der Rückgabewert ist weiterhin ein DataRow-Array.
In einer SQL-Abfrage legen Sie die Sortierreihenfolge der zurückgelieferten Datensätze mit der ORDER BY-Klausel fest. Beispielsweise gibt die folgende Abfrage alle Produkte sortiert nach ihrem Einzelpreis aus:
SELECT * FROM Products ORDER BY UnitPrice
Oder, um in absteigender Reihenfolge zu sortieren:
SELECT * FROM Products ORDER BY UnitPrice DESC
Genauso wie beim Filterkriterium verzichten Sie auf die Angabe der SQL-Klausel, hier also auf ORDER BY:
Dim rows() As DataRow = tbl.Select("ProductName LIKE 'C*'","UnitPrice DESC")
Um nur zu sortieren, übergeben Sie dem ersten Parameter der Methode eine leere Zeichenfolge:
Dim rows() As DataRow = tbl.Select("", "UnitPrice DESC")
Nach Zuständen suchen
Änderungen an einer Datenzeile werden durch deren Eigenschaft RowState beschrieben. Es gibt Situationen, in denen Sie sich für alle Datenzeilen interessieren, die editiert, hinzugefügt oder gelöscht worden sind. Um diese aus einer DataTable zu filtern, übergeben Sie der Select-Methode im dritten Parameter einen Wert der in Tabelle 26.8 gezeigten Enumeration DataViewRowState.
Konstante | Beschreibung |
Added |
Eine neue Zeile |
CurrentRows |
Aktuelle Zeilen, inklusive unveränderter, neuer und geänderter Zeilen |
Deleted |
Eine gelöschte Zeile |
ModifiedCurrent |
Geänderte Zeilen. Es wird der aktuelle Wert ausgegeben. |
ModifiedOriginal |
Geänderte Zeilen. Es wird der ursprüngliche Wert ausgegeben. |
None |
Keine. |
OriginalRows |
Ursprüngliche Zeilen, inklusive unveränderter und gelöschter Zeilen |
Unchanged |
Eine unveränderte Zeile |
Der folgende Befehl sucht nach gelöschten Datenzeilen:
Dim rows() As DataRow = tbl.Select("", "", DataViewRowState.Deleted)
Die ersten beiden Parameter erwarten den Filter- und Sortierausdruck. Sie können diesen beiden Parametern leere Zeichenfolgen übergeben. Der dritte Parameter schließlich erwartet die Angabe vom Typ DataViewRowState.
Warum ist der dritte Parameter nicht vom Typ DataRowState? Diese Enumeration (siehe Tabelle 26.5) könnte doch auch den Ansprüchen der Select-Methode entsprechen. Jedoch hat die DataViewRowState das Attribut Flags, das eine bitweise Verknüpfung erlaubt. So können Sie nach Datenzeilen suchen, die einen von mehreren Zuständen haben. Das nächste Beispiel sucht nach allen Datenzeilen, die gelöscht oder hinzugefügt worden sind:
Dim dvrs As DataViewRowState = _ DataViewRowState.Deleted | DataViewRowState.Added Dim rows() As DataRow = tbl.Select("", "", dvrs)
Wenn Sie sich das DataRow-Array anzeigen lassen, sollten Sie nicht vergessen, dass die gelöschten Datenzeilen nur in DataRowVersion.Original noch gültige Werte aufweisen.
Sollten Sie mit den beiden Konstanten ModifiedOriginal und ModifiedCurrent experimentieren, werden Sie feststellen, dass in beiden Fällen – entgegen der Beschreibung in der Tabelle – der aktuelle Wert angezeigt wird. Im Zusammenhang mit einer DataView funktionieren ModifiedOriginal und ModifiedCurrent wie beschrieben.
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.