Portada » Preguntas Frecuentes de .NET 6 » ¿Cómo cargar datos de una base de datos a un informe RDLC?

¿Cómo cargar datos de una base de datos a un informe RDLC?

Para cargar datos de la base de datos a un informe RDLC tenemos que añadir un elemento DataSet. Es importante destacar que es posible cargar múltiples DataSets a un mismo informe, pero en general no suele ser algo necesario.

👉 Para hacer uso de la explicación a continuación, tu proyecto (la librería de clases que creamos) debe contener el paquete NuGet «System.Data.SqlClient«.

Si aún no lo tienes añadido, te sugiero hacerlo antes de continuar.

Generando el DataSet y TableAdapters

Lo primero que hay que hacer es ir a nuestro proyecto ReportingModule y añadir una carpeta «Data» que nos sirva para contener los DataSets de nuestros reportes. Clic derecho sobre la carpeta > Añadir > Nuevo elemento y buscamos «DataSet» (Conjunto de datos si lo tenéis en español).

Conjunto de datos (DataSet) para cargar datos de una base de datos a nuestro informe RDLC.

Por lo general estaremos trabajando con un DataSet que tendrá múltiples TableAdapters. Si alguna vez habéis utilizado ADO.NET, estos conceptos os sonarán. Para añadir un TableAdapter, vamos a nuestro recién creado DataSet y le damos botón derecho sobre el fondo blanco y seleccionamos Añadir > TableAdapter.

Añadiendo TableAdapters a través de la interfaz

En este punto, el TableAdapter os mostrará un Wizard para ayudaros a generar la consulta que necesitáis. Lo primero será añadir una conexión a vuestra base de datos dando clic a «New Connection» y seleccionando el tipo que base de datos que utilizaréis.

Configuración del TableAdapter con el Wizard

Le dais a «Continue» y os salta una nueva ventana para añadir la conexión. Añadís la información necesaria para generar la conexión y probáis que la conexión sea correcta utilizando el botón «Test Connection». Si estás probando en local y usas MSSQL, lo más seguro es que en «Server name» tengas que poner algo de tipo:

(localdb)\MSSQLLocalDB

Que es el nombre por defecto del servidor local. Si el servidor es correcto y los datos de inicio de sesión son adecuados (Windows Authentication para localhost va bien), en el desplegable de selección de la base de datos a utilizar debería cargar automáticamente un listado de posibles bases de datos.

Si todo es correcto, le das a aceptar y continuas para poder generar la consulta SQL o utilizar algún Stored Procedure de tu base de datos.

Los métodos podéis mantener los que vienen por defecto y os creará un objeto en el DataSet. Esta es una breve explicación de cómo usar cada uno de ellos. Cabe destacar que el resultado del wizard me ha creado un objeto de tipo DataTable al que he dejado de nombre DataTable1 (importante para entender el ejemplo).

Fill a DataTable

Sirve para rellenar un objeto de tipo DataTable preexistente con el contenido proveniente de la consulta.

// DataSet que usamos en nuestro informe RDLC
Report1DataSet reportDataSet = new Report1DataSet();

// Adaptador de tipo DataTable1 que contiene la sentencia que acabamos de crear
DataTable1TableAdapter adapter = new DataTable1TableAdapter();

// El adaptador "injecta" los datos en el DataTable1 del reporte directamente
adapter.Fill(reportDataSet.DataTable1);

// Instanciamos el informe
LocalReport informe = new LocalReport();
informe.ReportPath = "-- inserta la ruta del RDLC --";

ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "DataSetCursos";
reportDataSource.Value = reportDataSet.DataTable1;


// Procedemos a cargar datos al informe RDLC
informe.DataSources.Add(reportDataSource);  

Return a DataTable

Genera un método que devuelve un DataTable relleno con los datos indicados.

// Generamos el adaptador
DataTable1TableAdapter adapter = new DataTable1TableAdapter();

// Obtenemos los datos mediante la función
DataTable dataTableIntermedio = adapter.GetData();

// Instanciamos el informe
LocalReport informe = new LocalReport();
informe.ReportPath = "-- inserta la ruta del RDLC --";

ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "DataSetCursos";
reportDataSource.Value = dataTableIntermedio;

// Procedemos a cargar datos al informe RDLC
informe.DataSources.Add(reportDataSource);    

¿La diferencia? Poca, realmente. De hecho, si tienes un repositorio, también puedes cargar los datos haciendo uso de una lista de objetos que tengas.

ReportDataSource reportDataSource = new ReportDataSource();
reportDataSource.Name = "DataSetCursos";

// El método puede devolver un tipo List<Curso> y también te lo acepta
reportDataSource.Value = _repositorioCurso.ObtenerTodos();

informe.DataSources.Add(reportDataSource);

La parte buena del sistema con datatables es evitar la necesidad de crear DTOs u objectos intermedios, pero si ya tienes los objetos creados para otras zonas de tu proyecto, entonces puedes aprovechar y reutilizar tus repositorios sin tener que pasar por construir datatables.

Así que usa el método que consideres más cómodo para tu proyecto o mézclalos si lo ves conveniente.

Cargar los datos al informe RDLC

Pese a que lo he adelantado ligeramente con el ejemplo anterior, en este punto necesitamos conectar una instancia de nuestro RDLC con una instancia de nuestros datos. Para usar los datos dentro de nuestro diseño, nuestro informe tiene que «saber» qué datos va a recibir y con qué esquema ha de esperarlos.

Es ahora cuando nos va a ser de utilidad el panel «Report Data» del que hablabamos en el artículo «Consideraciones a tener en cuenta al crear un informe RDLC«. En el panel le damos botón derecho a «DataSets» > «Add DataSet» y nos mostrará una ventana de selección.

Eligiendo dataset para nuestro informe RDLC

En la columna de «Fields» vemos el esquema de datos que va a esperar recibir nuestro informe.

¿Recordáis que en el ejemplo anterior creamos un objeto «ReportDataSource» y le asignamos un nombre y un valor? Esta parte es muy importante, pues el nombre asignado en el código debe coincidir con el nombre elegido para nuestro DataSet.

⚠ ¡Aviso navegantes! ⚠

Si os sale el error «Cannot create a data reader for dataset ‘NOMBRE_DE_TU_DATASET», significa que la propiedad «Name» de vuestro ReportDataSource no coincide con el nombre que habéis asignado al DataSet de vuestro informe RDLC.

PRO TIP: Si veis que no conseguís encontrar el nombre, podéis usar la siguiente función y hacer un punto de parada para consultar el valor de la variable datasourceNames.

LocalReport informe = new LocalReport();
informe.ReportPath = "-- tu ruta --";
var datasourceNames = informe.GetDataSourceNames()

En mi caso es «DataSetCursos» como podeis comprobar en la imagen y en el código de ejemplo del apartado anterior. Si los nombres no encajan, entonces el informe no podrá bindear los datos adecuadamente.

Ahora, con nuestro nuevo dataset creado, podemos añadir componentes del panel Toolbox dentro de nuestro reporte y bindearlos automáticamente a cualquiera de las propiedades de nuestro DataSetCursos.

Cargar datos a un informe RDLC en la carpeta DataSets para obtener todos los campos

Añadimos un objeto tipo tabla, damos botón derecho sobre el mismo y vamos a «Properties» para asignar nuestro dataset como fuente de datos de esa tabla.

Y ahora podemos hacer uso directo de esos datos dentro de nuestra tabla, de manera que las filas se generarán automáticamente dependiendo de cuantos datos nos devuelva la consulta del DataSetCursos.

Cargar datos a un informe RDLC dentro del tablix

Con la configuración indicada y haciendo una configuración mínima de un controlador MVC, el resultado obtenido sería algo tal que así:

Y con esto ya sabrías cargar datos a un informe RDLC desde las tablas de tu base de datos o usando listas de objetos derivados de tu capa de Dominio.