none
Buscar y ordenar datos en DataTable RRS feed

  • Pregunta

  • Hola tengo una duda al consultar datos en un DATATABLE en un modelo Carpetas/Archivos.

    Tengo 1 Datatable donde guardo dato de carpetas (id,nombre,nivel) y otro DataTable donde guardo los datos de archivos (id,nombre,id de la carpeta a la cual pertenece). Al recorrer el datatable de carpetas con un foreach, por cada carpeta busco sus archivos y se requiere que muestre los archivos ordenados por nombre. Busque alguna recomendación y sugieren crear un DataView sobre el Datatable de archivos ordenado por id de carpeta y nombre de archivo. Esto va a crear un indice que optimizara las búsquedas y la ordenación.

    Este es el codigo de ejemplo que tengo.

    // crear DataTable
    DataTable dtFolders = new DataTable();
    dtFolders.Columns.AddRange(new DataColumn[] { 
            new DataColumn("FolderID", typeof(int)), 
            new DataColumn("FolderName", typeof(string)), 
            new DataColumn("FolderLevel", typeof(int)) 
        });
    DataTable dtFiles = new DataTable();
    dtFiles.Columns.AddRange(new DataColumn[] { 
            new DataColumn("FileID", typeof(int)), 
            new DataColumn("FileName", typeof(string)), 
            new DataColumn("FolderID", typeof(int)) 
        });
    
    //llenar con datos de ejeplo .....
    
    var sbData = new StringBuilder(256);
    int level;
    
    // Crear DataView ordenado por FolderID, FileName sobre FILES, creando un INDICE para acelerar las busquedas
    var dwFiles = new DataView(dtFiles, "", "FolderID, FileName", DataViewRowState.CurrentRows);
    
    //recorrer las carpetas
    foreach (DataRow folder in dtFolders.Rows)
    {
        level = (int)folder["FolderLevel"];
        sbData.AppendLine(new String(' ', level) + folder["FolderName"]);
    
        //Buscar los archivos de la carpeta (ya estarian ordenados por nombre por como se creo el dataview)
        level += 1;
        foreach (DataRowView file in dwFiles.FindRows((int)folder["FolderID"])) //  aqui es donde tengo mi problema
        {
            sbData.AppendLine(new String(' ', level) + file["FileName"]);
        }
    }
    Console.WriteLine(sbData);


    Ahora bien esto da un error en tiempo de ejecucion porque el metodo FindRows espera 2 valores por como esta definido el ordenamiento de la dataView:

    "Expecting 2 value(s) for the key being indexed, but received 1 value(s)."

    Entonces probe de la siguiente manera. Pero solo muestra las carpetas (supongo que FindRows no soporta wildcard):

    foreach (DataRowView file in dwFiles.FindRows(new object[] { (int)folder["FolderID"], "*" })) 
    {
        sbData.AppendLine(new String(' ', level) + file["FileName"]);
    }

    intente consultar el DataView con linq y funciono.

    var filesQuery = from DataRowView file in dwFiles
                        where file.Row.Field<int>("FolderID") == (int)folder["FolderID"]
                        orderby file.Row.Field<string>("FileName") ascending
                        select new
                        {
                            FileName = file.Row.Field<string>("FileName")
                        };
    
    foreach (var file in filesQuery)
    {
        sbData.AppendLine(new String(' ', level) + file.FileName);
    }

    Pero consultar el datatable directamente con linq es mas rapido que consultar el dataview con linq. Supongo que mi consulta linq al Dataview no esta usando el indice que se creo:

    var files = from file in dtFiles.AsEnumerable()
                where file.Field<int>("FolderID") == (int)folder["FolderID"]
                orderby file.Field<string>("FileName") ascending
                select new
                {
                    FileName = file.Field<string>("FileName")
                };
    
    foreach (var file in files)
    {
        sbData.AppendLine(new String(' ', level) + file.FileName);
    }          

    Alguien puede responderme si realmente el linq al dataview no esta usando el indice? De que manera puedo usar el indice que eh creado con el dataview para acelerar la consulta? el linq al dataTable usa el indice del dataview o crea uno propio o no hace ninguna de las dos? Recomiendan otro método para hacer esto?

    Desde ya gracias!



    Juan Pablo Burgos



    viernes, 24 de octubre de 2014 14:42

Todas las respuestas