Freigeben über


Filtern mit DataView (LINQ to DataSet)

Die Möglichkeit zum Filtern von Daten mithilfe bestimmter Kriterien und anschließendes Darstellen der Daten an einen Client über ein UI-Steuerelement ist ein wichtiger Aspekt der Datenbindung. DataView bietet verschiedene Möglichkeiten, Daten zu filtern und Teilmengen von Datenzeilen zurückzugeben, die bestimmte Filterkriterien erfüllen. Zusätzlich zu den Zeichenfolgenbasierten Filterfunktionen bietet es auch die Möglichkeit, DataView LINQ-Ausdrücke für die Filterkriterien zu verwenden. LINQ-Ausdrücke ermöglichen viel komplexere und leistungsfähigere Filtervorgänge als die Zeichenfolgenbasierte Filterung.

Es gibt zwei Möglichkeiten zum Filtern von Daten mithilfe eines DataView:

  • Erstellen Sie eine DataView von einer LINQ to DataSet-Abfrage mit einer Where-Klausel.

  • Verwenden Sie die vorhandenen, zeichenfolgenbasierten Filterfunktionen von DataView.

Erstellen von DataView aus einer Abfrage mit Filterinformationen

Ein DataView Objekt kann aus einer LINQ to DataSet-Abfrage erstellt werden. Wenn diese Abfrage eine Where Klausel enthält, wird die DataView Abfrage mit den Filterinformationen aus der Abfrage erstellt. Der Ausdruck in der Where Klausel wird verwendet, um zu bestimmen, welche Datenzeilen in den DataView Filter eingeschlossen werden sollen, und bildet die Basis für den Filter.

Ausdrucksbasierte Filter bieten leistungsfähigere und komplexere Filter als die einfacheren Zeichenfolgenbasierten Filter. Die zeichenfolgenbasierten und ausdrucksbasierten Filter schließen sich gegenseitig aus. Wenn der zeichenfolgenbasierte RowFilter festgelegt wird, nachdem eine DataView auf der Grundlage einer Abfrage erstellt wurde, wird der ausdrucksbasierte Filter, der aus der Abfrage abgeleitet wurde, gelöscht.

Hinweis

In den meisten Fällen sollten die zum Filtern verwendeten Ausdrücke keine Nebenwirkungen haben und deterministisch sein. Außerdem sollten die Ausdrücke keine Logik enthalten, die von einer festgelegten Anzahl von Ausführungen abhängt, da die Filtervorgänge beliebig oft ausgeführt werden können.

Beispiel

Im folgenden Beispiel wird die Tabelle "SalesOrderDetail" nach Bestellungen mit einer Menge von mehr als 2 und weniger als 6 abgefragt; es wird ein DataView aus dieser Abfrage erstellt, und die DataView wird an BindingSource gebunden.

DataTable orders = _dataSet.Tables["SalesOrderDetail"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<short>("OrderQty") > 2 && order.Field<short>("OrderQty") < 6
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
Dim orders As DataTable = dataSet.Tables("SalesOrderDetail")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of Int16)("OrderQty") > 2 And _
          order.Field(Of Int16)("OrderQty") < 6 _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

Beispiel

Im folgenden Beispiel wird eine DataView Aus einer Abfrage für Bestellungen erstellt, die nach dem 6. Juni 2001 aufgegeben wurden:

DataTable orders = _dataSet.Tables["SalesOrderHeader"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<DateTime>("OrderDate") > new DateTime(2002, 6, 1)
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
Dim orders As DataTable = dataSet.Tables("SalesOrderHeader")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2002, 6, 1) _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

Beispiel

Die Filterung kann auch mit der Sortierung kombiniert werden. Im folgenden Beispiel wird eine DataView aus einer Abfrage für Kontakte erstellt, deren Nachnamen mit "S" beginnen und die nach Nachname und dann nach Vorname sortiert sind.

DataTable contacts = _dataSet.Tables["Contact"];

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where contact.Field<string>("LastName").StartsWith("S")
                                         orderby contact.Field<string>("LastName"), contact.Field<string>("FirstName")
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

Dim contacts As DataTable = dataSet.Tables("Contact")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where contact.Field(Of String)("LastName").StartsWith("S") _
    Order By contact.Field(Of String)("LastName"), contact.Field(Of String)("FirstName") _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

Beispiel

Im folgenden Beispiel wird der SoundEx-Algorithmus verwendet, um Kontakte zu finden, deren Nachname "Zhu" ähnelt. Der SoundEx-Algorithmus wird in der SoundEx-Methode implementiert.

DataTable contacts = _dataSet.Tables["Contact"];

var soundExCode = SoundEx("Zhu");

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where SoundEx(contact.Field<string>("LastName")) == soundExCode
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
Dim contacts As DataTable = dataSet.Tables("Contact")
Dim soundExCode As String = SoundEx("Zhu")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where SoundEx(contact.Field(Of String)("LastName")) = soundExCode _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

SoundEx ist ein phonetischer Algorithmus, der für die Indizierung von Namen nach Sound verwendet wird, da sie in Englisch ausgesprochen werden, das ursprünglich vom US Census Bureau entwickelt wurde. Die SoundEx-Methode gibt einen vierstelligen Code für einen Namen zurück, der aus einem englischen Buchstaben besteht, gefolgt von drei Zahlen. Der Buchstabe ist der erste Buchstabe des Namens, und die Zahlen codieren die verbleibenden Konsonanten im Namen. Ähnlich klingende Namen teilen denselben SoundEx-Code. Die in der SoundEx-Methode des vorherigen Beispiels verwendete SoundEx-Implementierung wird hier gezeigt:

static string SoundEx(string word)
{
    // The length of the returned code.
    const int length = 4;

    // Value to return.
    var value = "";

    // The size of the word to process.
    var size = word.Length;

    // The word must be at least two characters in length.
    if (size > 1)
    {
        // Convert the word to uppercase characters.
        word = word.ToUpper(CultureInfo.InvariantCulture);

        // Convert the word to a character array.
        var chars = word.ToCharArray();

        // Buffer to hold the character codes.
        var buffer = new StringBuilder
        {
            Length = 0
        };

        // The current and previous character codes.
        var prevCode = 0;
        var currCode = 0;

        // Add the first character to the buffer.
        buffer.Append(chars[0]);

        // Loop through all the characters and convert them to the proper character code.
        for (var i = 1; i < size; i++)
        {
            switch (chars[i])
            {
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':
                case 'H':
                case 'W':
                case 'Y':
                    currCode = 0;
                    break;
                case 'B':
                case 'F':
                case 'P':
                case 'V':
                    currCode = 1;
                    break;
                case 'C':
                case 'G':
                case 'J':
                case 'K':
                case 'Q':
                case 'S':
                case 'X':
                case 'Z':
                    currCode = 2;
                    break;
                case 'D':
                case 'T':
                    currCode = 3;
                    break;
                case 'L':
                    currCode = 4;
                    break;
                case 'M':
                case 'N':
                    currCode = 5;
                    break;
                case 'R':
                    currCode = 6;
                    break;
            }

            // Check if the current code is the same as the previous code.
            if (currCode != prevCode)
            {
                // Check to see if the current code is 0 (a vowel); do not process vowels.
                if (currCode != 0)
                {
                    buffer.Append(currCode);
                }
            }
            // Set the previous character code.
            prevCode = currCode;

            // If the buffer size meets the length limit, exit the loop.
            if (buffer.Length == length)
            {
                break;
            }
        }
        // Pad the buffer, if required.
        size = buffer.Length;
        if (size < length)
        {
            buffer.Append('0', length - size);
        }

        // Set the value to return.
        value = buffer.ToString();
    }
    // Return the value.
    return value;
}
Private Function SoundEx(ByVal word As String) As String

    Dim length As Integer = 4
    ' Value to return
    Dim value As String = ""
    ' Size of the word to process
    Dim size As Integer = word.Length
    ' Make sure the word is at least two characters in length
    If (size > 1) Then
        ' Convert the word to all uppercase
        word = word.ToUpper(System.Globalization.CultureInfo.InvariantCulture)
        ' Convert the word to character array for faster processing
        Dim chars As Char() = word.ToCharArray()
        ' Buffer to build up with character codes
        Dim buffer As StringBuilder = New StringBuilder()
        ' The current and previous character codes
        Dim prevCode As Integer = 0
        Dim currCode As Integer = 0
        ' Append the first character to the buffer
        buffer.Append(chars(0))
        ' Loop through all the characters and convert them to the proper character code
        For i As Integer = 1 To size - 1
            Select Case chars(i)

                Case "A", "E", "I", "O", "U", "H", "W", "Y"
                    currCode = 0

                Case "B", "F", "P", "V"
                    currCode = 1

                Case "C", "G", "J", "K", "Q", "S", "X", "Z"
                    currCode = 2

                Case "D", "T"
                    currCode = 3

                Case "L"
                    currCode = 4

                Case "M", "N"
                    currCode = 5

                Case "R"
                    currCode = 6
            End Select

            ' Check to see if the current code is the same as the last one
            If (currCode <> prevCode) Then

                ' Check to see if the current code is 0 (a vowel); do not process vowels
                If (currCode <> 0) Then
                    buffer.Append(currCode)
                End If
            End If
            ' Set the new previous character code
            prevCode = currCode
            ' If the buffer size meets the length limit, then exit the loop
            If (buffer.Length = length) Then
                Exit For
            End If
        Next
        ' Pad the buffer, if required
        size = buffer.Length
        If (size < length) Then
            buffer.Append("0", (length - size))
        End If
        ' Set the value to return
        value = buffer.ToString()
    End If
    ' Return the value
    Return value
End Function

Verwenden der "RowFilter"-Eigenschaft

Die vorhandene zeichenfolgenbasierte Filterfunktion DataView funktioniert weiterhin im LINQ to DataSet-Kontext. Weitere Informationen zur Zeichenfolgenbasierten RowFilter Filterung finden Sie unter Sortieren und Filtern von Daten.

Im folgenden Beispiel wird eine DataView aus der Tabelle "Kontakt" erstellt, und anschließend wird die RowFilter Eigenschaft so festgelegt, dass Zeilen zurückgegeben werden, in denen der Nachname des Kontakts "Zhu" lautet:

DataTable contacts = _dataSet.Tables["Contact"];

DataView view = contacts.AsDataView();

view.RowFilter = "LastName='Zhu'";

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim view As DataView = contacts.AsDataView()
view.RowFilter = "LastName='Zhu'"
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

Nachdem ein Objekt DataView aus einer DataTable Oder LINQ to DataSet-Abfrage erstellt wurde, können Sie die RowFilter Eigenschaft verwenden, um Teilmengen von Zeilen basierend auf ihren Spaltenwerten anzugeben. Die zeichenfolgenbasierten und ausdrucksbasierten Filter schließen sich gegenseitig aus. Wenn Sie die RowFilter Eigenschaft festlegen, wird der filterausdruck gelöscht, der von der LINQ to DataSet-Abfrage abgeleitet wurde, und der Filterausdruck kann nicht zurückgesetzt werden.

DataTable contacts = _dataSet.Tables["Contact"];

EnumerableRowCollection<DataRow> query = from contact in contacts.AsEnumerable()
                                         where contact.Field<string>("LastName") == "Hernandez"
                                         select contact;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

view.RowFilter = "LastName='Zhu'";
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim query = _
    From contact In contacts.AsEnumerable() _
    Where contact.Field(Of String)("LastName") = "Hernandez" _
    Select contact

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view

dataGridView1.AutoResizeColumns()
view.RowFilter = "LastName='Zhu'"

Wenn Sie die Ergebnisse einer bestimmten Abfrage für die Daten zurückgeben möchten, anstatt eine dynamische Ansicht einer Teilmenge der Daten bereitzustellen, können Sie die Find Methoden oder FindRows Methoden der DataViewEigenschaft verwenden, anstatt die RowFilter Eigenschaft festzulegen. Die RowFilter Eigenschaft wird am besten in einer datengebundenen Anwendung verwendet, in der ein gebundenes Steuerelement gefilterte Ergebnisse anzeigt. Wenn Sie die RowFilter Eigenschaft festlegen, wird der Index für die Daten neu erstellt, wodurch der Aufwand zu Ihrer Anwendung hinzugefügt und die Leistung verringert wird. Die Methoden Find und FindRows verwenden den aktuellen Index, ohne dass der Index neu erstellt werden muss. Wenn Sie Find oder FindRows nur einmal aufrufen, sollten Sie die vorhandene DataView verwenden. Wenn Sie Find oder FindRows mehrmals aufrufen möchten, sollten Sie einen neuen DataView erstellen, um den Index für die Spalte, nach der Sie suchen möchten, neu aufzubauen, und dann die Methoden Find oder FindRows aufrufen. Weitere Informationen zu den Find und FindRows Methoden finden Sie unter Suchen von Zeilen und DataView Performance.

Löschen des Filters

Der Filter für ein DataView Objekt kann gelöscht werden, nachdem die Filterung mithilfe der RowFilter Eigenschaft festgelegt wurde. Der Filter für ein Objekt DataView kann auf zwei verschiedene Arten gelöscht werden:

  • Legen Sie die RowFilter-Eigenschaft auf null fest.

  • Legen Sie die RowFilter Eigenschaft auf eine leere Zeichenfolge fest.

Beispiel

Das folgende Beispiel erstellt eine DataView aus einer Abfrage und löscht dann den Filter, indem die Eigenschaft RowFilter auf null gesetzt wird.

DataTable orders = _dataSet.Tables["SalesOrderHeader"];

EnumerableRowCollection<DataRow> query = from order in orders.AsEnumerable()
                                         where order.Field<DateTime>("OrderDate") > new DateTime(2002, 11, 20)
                                            && order.Field<decimal>("TotalDue") < new decimal(60.00)
                                         select order;

DataView view = query.AsDataView();

bindingSource1.DataSource = view;

view.RowFilter = null;
Dim orders As DataTable = dataSet.Tables("SalesOrderHeader")

Dim query = _
    From order In orders.AsEnumerable() _
    Where order.Field(Of DateTime)("OrderDate") > New DateTime(2002, 11, 20) _
        And order.Field(Of Decimal)("TotalDue") < New Decimal(60.0) _
    Select order

Dim view As DataView = query.AsDataView()
bindingSource1.DataSource = view
view.RowFilter = Nothing

Beispiel

Im folgenden Beispiel wird ein DataView aus einer Tabelle erstellt, wobei die RowFilter-Eigenschaft festgelegt wird. Anschließend wird der Filter gelöscht, indem die RowFilter-Eigenschaft auf eine leere Zeichenfolge gesetzt wird.

DataTable contacts = _dataSet.Tables["Contact"];

DataView view = contacts.AsDataView();

view.RowFilter = "LastName='Zhu'";

bindingSource1.DataSource = view;
dataGridView1.AutoResizeColumns();

// Clear the row filter.
view.RowFilter = "";
Dim contacts As DataTable = dataSet.Tables("Contact")

Dim view As DataView = contacts.AsDataView()
view.RowFilter = "LastName='Zhu'"
bindingSource1.DataSource = view
dataGridView1.AutoResizeColumns()

' Clear the row filter.
view.RowFilter = ""

Siehe auch