Compartir a través de


Filtrar con DataView (LINQ to DataSet)

La capacidad de filtrar datos mediante criterios específicos y, a continuación, presentar los datos a un cliente a través de un control de interfaz de usuario es un aspecto importante del enlace de datos. DataView proporciona varias maneras de filtrar datos y devolver subconjuntos de filas de datos que cumplen criterios de filtro específicos. Además de las funcionalidades de filtrado basadas en cadenas, DataView también proporciona la capacidad de usar expresiones LINQ para los criterios de filtrado. Las expresiones LINQ permiten operaciones de filtrado mucho más complejas y eficaces que el filtrado basado en cadenas.

Hay dos maneras de filtrar los datos mediante :DataView

  • Cree un objeto DataView a partir de una consulta de LINQ to DataSet con una cláusula Where.

  • Use las funcionalidades de filtrado existentes basadas en cadenas de DataView.

Creación de DataView a partir de una consulta con información de filtrado

Se puede crear un DataView objeto a partir de una consulta LINQ to DataSet. Si esa consulta contiene una Where cláusula, el DataView se crea con la información de filtrado de la consulta. La expresión de la Where cláusula se usa para determinar qué filas de datos se incluirán en DataViewy es la base del filtro.

Los filtros basados en expresiones ofrecen un filtrado más eficaz y complejo que los filtros basados en cadenas más sencillos. Los filtros basados en cadenas y basados en expresiones son mutuamente excluyentes. Cuando se establece el RowFilter basado en cadenas después de crear el DataView a partir de una consulta, se borra el filtro basado en expresiones inferido de la consulta.

Nota:

En la mayoría de los casos, las expresiones usadas para el filtrado no deben tener efectos secundarios y deben ser deterministas. Además, las expresiones no deben contener ninguna lógica que dependa de un número establecido de ejecuciones, ya que las operaciones de filtrado se pueden ejecutar en cualquier número de veces.

Ejemplo

En el ejemplo siguiente se consulta la tabla SalesOrderDetail para pedidos con una cantidad mayor que 2 y menor que 6; crea un objeto DataView a partir de esa consulta; y enlaza el DataView objeto a :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

Ejemplo

En el siguiente ejemplo, se crea un DataView a partir de una consulta para los pedidos realizados después del 6 de junio de 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

Ejemplo

El filtrado también se puede combinar con la ordenación. En el ejemplo siguiente se crea a partir de DataView una consulta para los contactos cuyo apellido empieza por "S" y se ordena por apellido y, a continuación, nombre:

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

Ejemplo

En el ejemplo siguiente se usa el algoritmo SoundEx para buscar contactos cuyo apellido es similar a "Zhu". El algoritmo SoundEx se implementa en el método 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 es un algoritmo fonético que se usa para indexar nombres por sonido, ya que se pronuncian en inglés, desarrollado originalmente por la Oficina del Censo estadounidense. El método SoundEx devuelve un código de cuatro caracteres para un nombre que consta de una letra en inglés seguida de tres números. La letra es la primera letra del nombre y los números codifican los consonantes restantes en el nombre. Los nombres de sonido similares comparten el mismo código SoundEx. La implementación de SoundEx usada en el método SoundEx del ejemplo anterior se muestra aquí:

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

Utilizar la propiedad RowFilter

La funcionalidad de filtrado basada en cadenas existente de DataView todavía funciona en el contexto LINQ to DataSet. Para obtener más información sobre el filtrado basado en RowFilter cadenas, vea Ordenar y filtrar datos.

En el ejemplo siguiente se crea un DataView elemento a partir de la tabla Contact y, a continuación, se establece la RowFilter propiedad para devolver filas donde el apellido del contacto es "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()

Después de crear un DataView a partir de LINQ to DataSet o de una consulta DataTable, puede usar la propiedad RowFilter para especificar subconjuntos de filas en función de sus valores de columna. Los filtros basados en cadenas y basados en expresiones son mutuamente excluyentes. Al establecer la RowFilter propiedad se borrará la expresión de filtro inferida de la consulta LINQ to DataSet y no se puede restablecer la expresión de filtro.

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

Si desea devolver los resultados de una consulta específica en los datos, en lugar de proporcionar una vista dinámica de un subconjunto de los datos, puede usar los métodos Find o FindRows del DataView, en lugar de establecer la propiedad RowFilter. La RowFilter propiedad se usa mejor en una aplicación enlazada a datos donde un control enlazado muestra los resultados filtrados. Al establecer la RowFilter propiedad se vuelve a generar el índice de los datos, se agrega sobrecarga a la aplicación y se reduce el rendimiento. Los Find métodos y FindRows usan el índice actual sin necesidad de volver a generar el índice. Si va a llamar a Find o a FindRows una única vez, entonces debería utilizar el DataView existente. Si va a llamar a Find o a FindRows varias veces, debe crear un nuevo DataView para volver a generar el índice en la columna en la que desea buscar, y después llamar a los métodos Find o FindRows. Para obtener más información sobre los Find métodos y FindRows , consulte Búsqueda de filas y rendimiento de DataView.

Borrar el filtro

El filtro en DataView se puede borrar después de que el filtrado haya sido establecido mediante la propiedad RowFilter. El filtro de una DataView se puede borrar de dos maneras diferentes:

  • Establezca la propiedad RowFilter en null.

  • Establezca la RowFilter propiedad en una cadena vacía.

Ejemplo

En el ejemplo siguiente se crea un DataView a partir de una consulta y, a continuación, se borra el filtro estableciendo la propiedad RowFilter en 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

Ejemplo

En el ejemplo siguiente se crea un DataView a partir de una tabla, se establece la RowFilter propiedad y, a continuación, se borra el filtro estableciendo la RowFilter propiedad en una cadena vacía:

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

Consulte también