Udostępnij za pośrednictwem


Filtrowanie za pomocą elementu DataView (LINQ to DataSet)

Możliwość filtrowania danych przy użyciu określonych kryteriów, a następnie prezentowania danych klientowi za pomocą kontrolki interfejsu użytkownika jest ważnym aspektem powiązania danych. DataView Udostępnia kilka sposobów filtrowania danych i zwracania podzestawów wierszy danych spełniających określone kryteria filtrowania. Oprócz możliwości filtrowania opartego na ciągach DataView zapewnia również możliwość używania wyrażeń LINQ dla kryteriów filtrowania. Wyrażenia LINQ umożliwiają znacznie bardziej złożone i zaawansowane operacje filtrowania niż filtrowanie oparte na ciągach.

Istnieją dwa sposoby filtrowania danych przy użyciu elementu DataView:

  • Utwórz element DataView na podstawie zapytania LINQ to DataSet z klauzulą Where.

  • Użyj istniejących funkcji filtrowania opartego na ciągach w programie DataView.

Tworzenie elementu DataView na podstawie zapytania z informacjami dotyczącymi filtrowania

Obiekt DataView można utworzyć na podstawie zapytania LINQ to DataSet. Jeśli to zapytanie zawiera klauzulę Where , DataView zostanie ona utworzona przy użyciu informacji filtrowania z zapytania. Wyrażenie w klauzuli Where służy do określania, które wiersze danych zostaną uwzględnione w elemecie DataView, i jest podstawą filtru.

Filtry oparte na wyrażeniach oferują bardziej zaawansowane i złożone filtrowanie niż prostsze filtry oparte na ciągach. Filtry oparte na ciągach i wyrażeniach wykluczają się wzajemnie. Po ustawieniu ciągu RowFilter po DataView utworzeniu elementu na podstawie zapytania filtr na podstawie wyrażenia wywnioskowanego z zapytania zostanie wyczyszczone.

Uwaga

W większości przypadków wyrażenia używane do filtrowania nie powinny mieć skutków ubocznych i muszą być deterministyczne. Ponadto wyrażenia nie powinny zawierać żadnej logiki, która zależy od określonej liczby wykonań, ponieważ operacje filtrowania mogą być wykonywane dowolną liczbę razy.

Przykład

Poniższy przykład wysyła zapytanie do tabeli SalesOrderDetail dla zamówień o ilości większej niż 2 i mniejszej niż 6; tworzy element DataView na podstawie tego zapytania i wiąże element z DataView elementem BindingSource:

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

Przykład

Poniższy przykład tworzy zapytanie DataView dotyczące zamówień złożonych po 6 czerwca 2001 r.:

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

Przykład

Filtrowanie można również łączyć z sortowaniem. Poniższy przykład tworzy element DataView na podstawie zapytania dla kontaktów, których nazwisko zaczyna się od "S" i posortowane według nazwiska, a następnie imię:

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()

Przykład

W poniższym przykładzie użyto algorytmu SoundEx, aby znaleźć kontakty, których nazwisko jest podobne do "Zhu". Algorytm SoundEx jest implementowany w metodzie SoundEx.

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 to algorytm fonetyczny używany do indeksowania nazw według dźwięku, ponieważ są one wymawiane w języku angielskim, pierwotnie opracowane przez Us Census Bureau. Metoda SoundEx zwraca czteroznaczny kod nazwy składającej się z angielskiej litery, po której następuje trzy cyfry. Litera jest pierwszą literą nazwy, a cyfry kodują pozostałe spółgłoski w nazwie. Podobne nazwy brzmiące mają ten sam kod SoundEx. Implementacja SoundEx używana w metodzie SoundEx poprzedniego przykładu jest pokazana tutaj:

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

Używanie właściwości RowFilter

Istniejące funkcje filtrowania oparte na ciągach DataView nadal działają w kontekście LINQ to DataSet. Aby uzyskać więcej informacji na temat filtrowania opartego na RowFilter ciągach, zobacz Sortowanie i filtrowanie danych.

Poniższy przykład tworzy obiekt DataView z tabeli Contact, a następnie ustawia RowFilter właściwość tak, aby zwracała wiersze, w których nazwisko kontaktu to "Zhu":

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()

Po utworzeniu elementu DataView na podstawie DataTable zapytania LINQ to DataSet można użyć RowFilter właściwości , aby określić podzestawy wierszy na podstawie ich wartości kolumn. Filtry oparte na ciągach i wyrażeniach wykluczają się wzajemnie. RowFilter Ustawienie właściwości spowoduje wyczyszczenie wyrażenia filtru wywnioskowanego z zapytania LINQ to DataSet i nie można zresetować wyrażenia filtru.

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'"

Jeśli chcesz zwrócić wyniki określonego zapytania dotyczącego danych, w przeciwieństwie do zapewnienia dynamicznego widoku podzestawu danych, możesz użyć Find metod DataViewlub FindRows , a nie ustawiania RowFilter właściwości . Właściwość RowFilter jest najlepiej używana w aplikacji powiązanej z danymi, w której powiązana kontrolka wyświetla przefiltrowane wyniki. RowFilter Ustawienie właściwości ponownie kompiluje indeks dla danych, dodając obciążenie do aplikacji i zmniejszając wydajność. Metody Find i FindRows używają bieżącego indeksu bez konieczności odbudowy indeksu. Jeśli zamierzasz zadzwonić Find lub FindRows tylko raz, należy użyć istniejącego DataViewelementu . Jeśli zamierzasz wywołać Find metodę lub FindRows wielokrotnie, utwórz nową DataView , aby ponownie skompilować indeks w kolumnie, w której chcesz wyszukać, a następnie wywołać Find metody lub FindRows . Aby uzyskać więcej informacji na temat Find metod i FindRows , zobacz Znajdowanie wierszy i wydajności widoku danych.

Czyszczenie filtru

Filtr dla elementu DataView można wyczyścić po ustawieniu filtrowania RowFilter przy użyciu właściwości . Filtr dla elementu DataView można wyczyścić na dwa różne sposoby:

Przykład

Poniższy przykład tworzy obiekt DataView na podstawie zapytania, a następnie czyści filtr, ustawiając RowFilter właściwość na :null

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

Przykład

Poniższy przykład tworzy obiekt DataView na podstawie tabeli ustawia RowFilter właściwość, a następnie czyści filtr, ustawiając RowFilter właściwość na pusty ciąg:

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 = ""

Zobacz też