Ejemplo DataSetHelper ¿Utilizar una instrucción Group By de SQL (Structure Query Language) dentro de un objeto DataTable?, suena raro, ¿Porqué debería utilizar esta forma de agrupar registros cuando puedo utilizar esta instrucción directamente en un Stored Procedure al momento de recuperar los datos?. Pues pueden haber casos en los cuales no se puedan agrupar los datos directamente desde la Base de Datos, por ejemplo: si tenemos que poblar un DataTable utilizando diferentes fuentes de datos, como: una BD de SQL y una BD de Oracle y un archivo XML, con los mismos campos, pero que contienen registros que al unir en un mismo DataTable resulten duplicados, entonces no sería posible utilizar el famoso Group By al recuperar los datos de la Base de Datos no?

Pues bien, sin ir con tanto rodeo, hay una clase que podemos utilizar para resolver este problema, la clase se llama DataSetHelper; si, así como existió en su momento un SQLHelper y luego un OracleHelper, ahora resulta que existe un DataSetHelper, el cual contiene la forma de resolver este impase. Sin embargo, según mis “investigaciones codigueriles” (es un término mio que pienso patentar… JA!, se refiere a analizar el código) hay un problema al agregar nuevas filas al DataTable, que no permite unir los nuevos registros iguales, lo cual hace que algunos se repitan.

Tomaremos como ejemplo la imágen del lado, las 2 primeras filas han sido agregadas al cargar al WindowsForm, pero el resto se ha agregado utilizando las cajas de texto y el botón Agregar; en un principio, esto resultaba con la suma de las 2 primeras filas y luego se copiaba el resto de filas sin generar la sumatoria ni el agrupamiento. Al modificar el código y agregarle solo un par de validaciones obtengo el resultado que se ve en la grilla de la parte inferior, es decir, el agrupamiento, el conteo de registros y la sumatoria deseados.

Además de ello también he agregado una condición para que, si existiese la tabla resultante en el dataset, sea borrada y reemplazada por una nueva, por lo que se debe tener cuidado con el nombre que se le asignará, esto me evita el que se produzca una excepción en caso la tabla ya existe.

La sintáxis para poder efectuar este proceso, tomando como referencia el ejemplo de la imágen, es la siguiente:

DataSetHelper dsh = new DataSetHelper(ref dts);
dgvResultado.DataSource = dsh.SelectGroupByInto("Resultado", dts.Tables["Inicio"],
"Local,count(Local) Cantidad,Sum(Total) Totales", "Total>0", "Local");

Ahora explicaremos un poco como funciona esta llamada: Se instancia la clase DataSetHelper pasándole como argumento el DataSet con el que se va a trabajar, pero como referencia, es decir, que cuando se haga algún cambio en el DataSet dentro de la clase, éste será afectado en el contexto original.

Para obtener el resultado debemos invocar al método SelectGroupByInto, el cual devuelve un objeto de tipo DataSet, para hacerlo debemos pasarle como argumento los siguentes datos: un string que contiene el nombre del DataTable resultante, el Objeto DataTable inicial a partir del cual se agruparán los datos, una cadena que contiene la lista de campos que debe evaluarse, en este caso haremos una explicación adicional; la lista de campos debe contener el siguiente formato: [<Funcion de Agregado>] <Nombre de Campo>. Los últimos parámetros necesario son: el filtro que se debe tomar en cuenta y el campo por el cual se debe agrupar.

En la web de Microsoft en la cual se encuentra esta utilidad, además se encuentran los pasos que se requieren para utilizarlos.

Pueden descargar el código con el ejemplo de la imágen y las modificaciones comentariadas a través del siguiente enlace: Descargar Ejemplo DataSetHelper

URL: http://support.microsoft.com/default.aspx?scid=kb;en-us;326145 (inglés)
http://support.microsoft.com/kb/326145/es (español)

Espero que les sea de utilidad.

Saludos.