Rendimiento con respecto al tipo de retorno para consultas LINQ compatibles con clasificación automática

StackOverflow https://stackoverflow.com/questions/1761597

Pregunta

Esto no es realmente un problema, sino más bien una preocupación sobre la que agradecería algún comentario, por favor.

Winforms C# .net3.5[sp1] Visual Studio 2008 usando Linq2Sql (más específicamente PLINQO... ¡lo cual es fantástico por cierto!).Tengo un conjunto de resultados que devuelve +/- 19000 filas de datos (con aproximadamente 80 bytes de datos por fila) y opté por enviar el método de recuperación de datos a un segundo plano y actualizar la interfaz de usuario en consecuencia.Esto funciona bien.

Sin embargo, he notado algunas diferencias de rendimiento al utilizar diferentes tipos de devolución para mi método de recuperación de datos Ling.Sé que todo el mundo sugiere devolver un List<T> o IEnumarable<T>, y configure la fuente de datos de DataGridView en eso, pero desafortunadamente no admite la clasificación de objetos de forma nativa.Después de investigar un poco encontré el SortableBindingList<T> en MSDN aquí.Lo apliqué y la cuadrícula tardó menos de un segundo en completarse; sin embargo, cuando hago clic en una columna para ordenarla, me tomó un poco más de un segundo implementar la clasificación.

Luego decidí seguir la ruta DataTable, pero descubrí que el método ToDataTable había sido eliminado, pero después de investigar más encontré una manera de implementarlo en esto. artículo de MSDN.Después de aplicarlo, descubrí que la recuperación tomó aproximadamente 2 segundos para completar la cuadrícula, pero luego la clasificación (¡en 19000 filas!) fue instantánea.Naturalmente, me quedé con este enfoque.

También tenga en cuenta que he desactivado cualquier edición, adición o eliminación en la cuadrícula.La cuadrícula es exclusivamente para mostrar datos.Cualquier otra operación CRUD se proporciona mediante formularios de diálogo de acuerdo con la fila seleccionada actual (columna de clave principal oculta).

Aquí está el código que utilicé para ambos métodos:

1) Lista de enlaces ordenables

    //declare private member
    private SortableBindingList<PdtAllocation> listAlloc = null;

    private void RefreshData() {
        bcsDataContext ctx = new bcsDataContext();
        try {
            listAlloc = new SortableBindingList<PdtAllocation>(ctx.PdtAllocation.ToList());
        }
        catch (Exception) {
            throw;
        }
        finally {
            ctx.Dispose();
        }

        dataGridView1.DataSource = listAlloc;
    }

2) Copiar a tabla de datos

    //declare private member
    private DataTable dt = null;

    private void RefreshData() {
        dt = new DataTable();
        bcsDataContext ctx = new bcsDataContext();
        try {
            ctx.PdtAllocation.CopyToDataTable(dt, LoadOption.PreserveChanges);
        }
        catch (Exception) {
            throw;
        }
        finally {
            ctx.Dispose();
        }

        dataGridView1.DataSource = dt;
    }

Ahora sé que esto probablemente parezca un "preguntado y respondido" caso, pero realmente agradecería su opinión, así como cualquier problema conocido con el proceso CopyToDataTable() ruta.

Gracias... ¡y disculpas por la larga consulta!

¿Fue útil?

Solución

Aquí está mi opinión sobre tu pregunta (yendo por el SortableBindingList ruta).

¿Utilizó un algoritmo de clasificación genérico basado en reflexión?Hice esto al principio y el rendimiento fue realmente malo.Finalmente se me ocurrió la siguiente solución:proporcionar clasificación predeterminada en SortableBindingList<T> pero también deja abierta la posibilidad de implementar una clasificación especializada en clases derivadas.

Aquí hay un código.

En SortableBindingList<T>.ApplySortCore():

protected override void ApplySortCore(PropertyDescriptor prop, ListSortDirection direction)
{
    // Check if the sorted property implements IComparable
    ...

    List<T> itemsList = (List<T>)this.Items;

    Comparison<T> comparer = GetComparer(prop);

    itemsList.Sort(comparer);

    if (direction == ListSortDirection.Descending)
    {
        itemsList.Reverse();
    }

    ...
    // Set sort state (is sorted, sort property, sort dir)
}

el generico SortableBindingList<T> proporciona un clasificador básico basado en reflexión:

protected virtual Comparison<T> GetComparer(PropertyDescriptor prop)
{
    return new Comparison<T>(delegate(T x, T y)
    {
        if (prop.GetValue(x) != null)
            return ((IComparable)prop.GetValue(x)).CompareTo(prop.GetValue(y));
        else if (prop.GetValue(y) != null)
            return -1 * ((IComparable)prop.GetValue(y)).CompareTo(prop.GetValue(x));
        else
            return 0;
    });
}

Como se puede ver, GetComparer() es virtual, por lo que se puede anular en una clase derivada de SortableBindingList<T> con el fin de proporcionar un mucho comparador más rápido, ajustado al tipo de propiedad que realmente se clasifica.Por ejemplo, mientras el comparador genérico ordenaba (por un String propiedad) 10000 registros en 4 segundos, el comparador especializado hizo el mismo trabajo en 70 ms.

class CustomerList : SortableBindingList<Customer>
{
    protected override Comparison<Customer> GetComparer(PropertyDescriptor prop)
    {
        Comparison<Customer> comparer = null;
        switch (prop.Name)
        {
            case "FirstName":
                comparer = new Comparison<Customer>(delegate(Customer x, Customer y)
                {
                    string xx = (null == x) ? null : x.FirstName;
                    string yy = (null == y) ? null : y.FirstName;
                    return String.Compare(xx, yy);
                });
                break;
            ...
        }
        return comparer;
    }
}

Una nota final:Gran parte del código publicado fue copiado/inspirado de otras fuentes, como SO o Microsoft, por lo que el crédito no es mío.Mi única contribución fue virtualizar el comparador, pero estoy seguro de que buscar un poco en Google arrojaría mejores soluciones anteriores basadas en la misma idea.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top