Dela via


Filtrering med DataView (LINQ till DataSet)

Möjligheten att filtrera data med hjälp av specifika kriterier och sedan presentera data för en klient via en användargränssnittskontroll är en viktig aspekt av databindningen. DataView innehåller flera sätt att filtrera data och returnera delmängder av datarader som uppfyller specifika filtervillkor. Utöver de strängbaserade filtreringsfunktionerna DataView kan du även använda LINQ-uttryck för filtreringsvillkoren. LINQ-uttryck möjliggör mycket mer komplexa och kraftfulla filtreringsåtgärder än strängbaserad filtrering.

Det finns två sätt att filtrera data med hjälp av :DataView

  • Skapa en DataView från en LINQ till DataSet-fråga med en Where-sats.

  • Använd de befintliga, strängbaserade filtreringsfunktionerna DataViewi .

Skapa DataView från en fråga med filtreringsinformation

Ett DataView objekt kan skapas från en LINQ till DataSet-fråga. Om frågan innehåller en Where sats skapas den DataView med filtreringsinformationen från frågan. Uttrycket i Where -satsen används för att avgöra vilka datarader som ska ingå i DataView, och är grunden för filtret.

Uttrycksbaserade filter erbjuder mer kraftfull och komplex filtrering än de enklare strängbaserade filtren. De strängbaserade och uttrycksbaserade filtren är ömsesidigt uteslutande. När strängbaserad RowFilter anges efter att en DataView har skapats från en fråga rensas det uttrycksbaserade filter som härleds från frågan.

Kommentar

I de flesta fall bör de uttryck som används för filtrering inte ha biverkningar och måste vara deterministiska. Dessutom bör uttrycken inte innehålla någon logik som är beroende av ett angivet antal körningar, eftersom filtreringsåtgärderna kan köras valfritt antal gånger.

Exempel

I följande exempel efterfrågas tabellen SalesOrderDetail för beställningar med en kvantitet som är större än 2 och mindre än 6. skapar en DataView från den frågan och binder DataView till :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

Exempel

I följande exempel skapas en DataView från en fråga för beställningar som gjorts efter den 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

Exempel

Filtrering kan också kombineras med sortering. I följande exempel skapas en DataView från en fråga för kontakter vars efternamn börjar med "S" och sorteras efter efternamn och sedan förnamn:

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

Exempel

I följande exempel används SoundEx-algoritmen för att hitta kontakter vars efternamn liknar "Zhu". SoundEx-algoritmen implementeras i Metoden 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 är en fonetikalgoritm som används för att indexera namn efter ljud, eftersom de uttalas på engelska, som ursprungligen utvecklades av U.S. Census Bureau. Metoden SoundEx returnerar en kod med fyra tecken för ett namn som består av en engelsk bokstav följt av tre siffror. Bokstaven är den första bokstaven i namnet och numren kodar de återstående konsonanterna i namnet. Liknande ljudnamn delar samma SoundEx-kod. SoundEx-implementeringen som används i SoundEx-metoden i föregående exempel visas här:

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

Använda egenskapen RowFilter

De befintliga strängbaserade filtreringsfunktionerna DataView i fungerar fortfarande i LINQ till DataSet-kontexten. Mer information om strängbaserad RowFilter filtrering finns i Sortera och filtrera data.

Följande exempel skapar en DataView från tabellen Kontakt och anger RowFilter sedan egenskapen för att returnera rader där kontaktens efternamn är "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()

När en DataView har skapats från en DataTable eller LINQ till DataSet-fråga kan du använda RowFilter egenskapen för att ange delmängder av rader baserat på deras kolumnvärden. De strängbaserade och uttrycksbaserade filtren är ömsesidigt uteslutande. RowFilter Om du anger egenskapen rensas filteruttrycket som härleds från LINQ till DataSet-frågan och filteruttrycket kan inte återställas.

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

Om du vill returnera resultatet av en viss fråga på data, i stället för att tillhandahålla en dynamisk vy av en delmängd av data, kan du använda Find metoderna eller FindRows i DataView, i stället för att ange RowFilter egenskapen. Egenskapen RowFilter används bäst i ett databundet program där en bunden kontroll visar filtrerade resultat. RowFilter Om du ställer in egenskapen återskapas indexet för data, om du lägger till omkostnader i ditt program och minskar prestandan. Metoderna Find och FindRows använder det aktuella indexet utan att behöva återskapa indexet. Om du bara ska anropa Find eller FindRows en gång bör du använda den befintliga DataView. Om du ska anropa Find eller FindRows flera gånger bör du skapa en ny DataView för att återskapa indexet på kolumnen som du vill söka efter och sedan anropa Find metoderna eller FindRows . Mer information om metoderna och finns FindRows i Find Hitta rader och DataView-prestanda.

Rensa filtret

Filtret på en DataView kan rensas när filtrering har angetts med hjälp av RowFilter egenskapen . Filtret på en DataView kan rensas på två olika sätt:

Exempel

Följande exempel skapar en DataView från en fråga och rensar sedan filtret genom att ange RowFilter egenskapen till 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

Exempel

I följande exempel skapas en DataView från en tabell som anger RowFilter egenskapen och rensar sedan filtret genom att ställa in RowFilter egenskapen på en tom sträng:

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

Se även