Bagikan melalui


Memfilter dengan DataView (LINQ to DataSet)

Kemampuan untuk memfilter data menggunakan kriteria tertentu lalu menyajikan data ke klien menggunakan kontrol UI merupakan aspek penting dari pengikatan data. DataView menyediakan beberapa cara untuk memfilter data dan mengembalikan subset baris data yang memenuhi kriteria filter tertentu. Selain menyediakan kemampuan pemfilteran berbasis string, DataView juga menyediakan kemampuan dalam menggunakan ekspresi LINQ untuk kriteria pemfilteran. Ekspresi LINQ memungkinkan operasi pemfilteran yang jauh lebih kompleks dan kuat daripada pemfilteran berbasis string.

Terdapat dua cara untuk memfilter data menggunakan DataView:

  • Buat DataView dari kueri LINQ to DataSet dengan klausa Where.

  • Gunakan kemampuan pemfilteran berbasis string yang ada dari DataView.

Membuat DataView dari Kueri dengan Informasi Pemfilteran

Objek DataView dapat dibuat dari kueri LINQ ke DataSet. Jika kueri tersebut berisi klausa Where, DataView akan dibuat dengan informasi pemfilteran dari kueri. Ekspresi dalam klausa Where digunakan untuk menentukan baris data yang akan disertakan di DataView, dan merupakan dasar untuk filter tersebut.

Filter berbasis ekspresi menawarkan pemfilteran yang lebih kuat dan kompleks daripada filter berbasis string yang lebih sederhana. Filter berbasis string dan berbasis ekspresi bersifat saling eksklusif. Saat RowFilter berbasis string diatur setelah DataView dibuat dari kueri, filter berbasis ekspresi yang disimpulkan dari kueri akan dibersihkan.

Catatan

Pada kebanyakan kasus, ekspresi yang digunakan untuk pemfilteran tidak boleh memiliki efek samping dan harus deterministik. Selain itu, ekspresi tidak boleh berisi logika apa pun yang bergantung pada sejumlah eksekusi yang ditetapkan karena operasi pemfilteran mungkin akan dijalankan beberapa kali.

Contoh

Contoh berikut mengkueri tabel SalesOrderDetail untuk pesanan dengan kuantitas lebih besar dari 2 dan kurang dari 6; membuat DataView dari kueri tersebut; dan mengikat DataView ke 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

Contoh

Contoh berikut membuat DataView dari kueri untuk pesanan yang dilakukan setelah 6 Juni 2001:

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

Contoh

Pemfilteran juga dapat dikombinasikan dengan pengurutan. Contoh berikut membuat DataView dari kueri untuk kontak yang nama belakangnya dimulai dengan huruf "S" dan diurutkan berdasarkan nama belakang lalu nama depan:

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

Contoh

Contoh berikut menggunakan algoritma SoundEx untuk menemukan kontak yang nama belakangnya mirip dengan "Zhu". Algoritma SoundEx diimplementasikan dalam metode 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 adalah algoritma fonetik yang digunakan untuk mengindeks nama berdasarkan bunyi, karena diucapkan dalam bahasa Inggris, yang pada awalnya dikembangkan oleh Biro Sensus AS. Metode SoundEx mengembalikan kode empat karakter untuk nama yang terdiri dari huruf bahasa Inggris diikuti dengan tiga angka di belakangnya. Huruf tersebut adalah huruf pertama dari nama dan angka-angka yang mengodekan konsonan yang tersisa dalam nama tersebut. Nama yang berbunyi mirip akan memiliki kode SoundEx yang sama. Implementasi SoundEx yang digunakan dalam metode SoundEx dari contoh sebelumnya ditunjukkan di sini:

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

Menggunakan Properti RowFilter

Fungsionalitas pemfilteran berbasis string yang ada dari DataView masih berfungsi dalam konteks LINQ to DataSet. Untuk informasi selengkapnya tentang pemfilteran RowFilter berbasis string, baca Mengurutkan dan Memfilter Data.

Contoh berikut membuat DataView dari tabel Kontak lalu mengatur properti RowFilter untuk menghasilkan baris yang memiliki nama belakang kontak "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()

Setelah DataView dibuat dari DataTable atau kueri LINQ to DataSet, Anda dapat menggunakan properti RowFilter untuk menentukan subset baris berdasarkan nilai kolomnya. Filter berbasis string dan berbasis ekspresi bersifat saling eksklusif. Mengatur properti RowFilter akan menghapus ekspresi filter yang disimpulkan dari kueri LINQ to DataSet dan ekspresi filter tidak dapat diatur ulang.

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

Jika Anda ingin mengembalikan hasil kueri tertentu pada data, berbeda dari menyediakan tampilan dinamis subset data, Anda dapat menggunakan metode Find atau FindRows dari DataView, daripada mengatur properti RowFilter. Properti RowFilter paling baik digunakan dalam aplikasi yang terikat data tempat kontrol terikat menampilkan hasil yang difilter. Mengatur properti RowFilter akan membangun kembali indeks untuk data yang menambahkan overhead ke aplikasi Anda dan mengurangi performa. Metode Find dan FindRows menggunakan indeks saat ini tanpa mengharuskan indeks dibangun kembali. Jika Anda hanya akan memanggil Find atau FindRows sekali, maka Anda harus menggunakan DataView yang ada. Jika Anda akan memanggil Find atau FindRows beberapa kali, Anda harus membuat DataView baru untuk membangun kembali indeks pada kolom yang ingin Anda telusuri, lalu memanggil metode Find atau FindRows. Untuk informasi selengkapnya tentang metode Find dan FindRows lihat Menemukan Baris dan Performa DataView.

Membersihkan Filter

Filter pada DataView dapat dibersihkan setelah pemfilteran diatur dengan menggunakan properti RowFilter. Filter pada DataView dapat dibersihkan dengan dua cara yang berbeda:

Contoh

Contoh berikut membuat DataView dari kueri lalu menghapus filter dengan mengatur properti RowFilter ke 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

Contoh

Contoh berikut membuat DataView dari tabel yang mengatur properti RowFilter lalu membersihkan filter dengan mengatur properti RowFilter ke string kosong:

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

Lihat juga