Durante el desarrollo de una rutina en VB.NET para exportar datos y pasar parámetros a través de la sesión, revisé una estructura inicial basada en Hashtable y tipos primitivos con el fin de asegurar una correcta integración con bases de datos MSSQL.
1. El código inicial y sus detalles
El código original cumplía con el flujo básico de capturar valores desde controles DropDownList, agregarlos a una estructura de almacenamiento y redirigir al usuario hacia un módulo de reportes:
Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
Dim ParametrosRpt As New Hashtable
Dim status As Integer = Nothing
Dim motive As Long = Nothing
Dim term As Long = Nothing
Dim year As Integer = Nothing
If ddlAcademicStatuses.SelectedValue <> "-1" Then
status = ddlAcademicStatuses.SelectedValue
End If
If ddlAcademicMotives.SelectedValue <> "-1" Then
motive = ddlAcademicMotives.SelectedValue
End If
If ddlTerms.SelectedValue <> "-2" Then
term = ddlTerms.SelectedValue
End If
If ddlYears.SelectedValue <> "-2" Then
year = ddlYears.SelectedValue
End If
ParametrosRpt.Add("NombreReporte", "grades_report_horizontal")
ParametrosRpt.Add("PaginaAnterior", Request.ServerVariables("URL"))
ParametrosRpt.Add("status", status)
ParametrosRpt.Add("motive", motive)
ParametrosRpt.Add("term", term)
ParametrosRpt.Add("year", year)
Session.Add("ParametrosRpt", ParametrosRpt)
Response.Redirect("~/desarrollo/Reportes/Reportes.aspx", False)
End Sub
2. Puntos de mejora identificados
Aunque la estructura general operaba correctamente, se detectaron varios aspectos clave a optimizar para garantizar robustez y rendimiento:
- Inicialización de variables: Las variables se declaraban como tipos de valor estándar (`Integer`, `Long`) inicializadas con
Nothing, lo cual en VB.NET asigna implícitamente el valor predeterminado del tipo (en este caso0) en lugar de una ausencia real de valor. - Validación de DropDownList: El uso de valores centinela como
"-1"o"-2"dependía estrictamente de la coherencia en el frontend, por lo que las conversiones debían manejarse de forma más controlada. - Uso de Hashtable: Aunque funcional,
Hashtablealmacena elementos comoObjectrequiriendo operaciones de boxing/unboxing. En .NET moderno es preferible utilizarDictionary(Of String, Object)por tipado y rendimiento. - Manejo de Sesión: Se utilizaba
Session.Add, el cual puede generar excepciones si la clave ya existe, siendo más limpio asignar directamente mediante el índiceSession("ParametrosRpt") = ....
3. El problema del valor NULL frente a MSSQL
El requerimiento principal era asegurar que si las condiciones de selección no se cumplían, las variables permanecieran estrictamente como nulas para que se tradujeran como NULL en las consultas ejecutadas en MSSQL. Un tipo primitivo como Integer no puede almacenar un nulo real; si se deja sin valor, toma 0, lo cual puede interpretarse erróneamente en la base de datos como un identificador válido.
Integer, este adopta el valor 0. Si tu base de datos acepta nulos para representar la ausencia de filtro, enviar un 0 alterará los resultados del reporte comparado con enviar un NULL real.
4. La solución: Tipos anulables y Dictionary
Para resolver esto, la estrategia consistió en adoptar tipos anulables (Nullable Types) añadiendo el sufijo ? a las declaraciones (como Integer? o Long?), permitiendo que conserven el estado Nothing de manera explícita y se mapeen correctamente a NULL en el motor de base de datos.
Private Sub btnExport_Click(sender As Object, e As EventArgs) Handles btnExport.Click
Dim ParametrosRpt As New Dictionary(Of String, Object)
Dim status As Integer? = Nothing
Dim motive As Long? = Nothing
Dim term As Long? = Nothing
Dim year As Integer? = Nothing
If ddlAcademicStatuses.SelectedValue <> "-1" Then
status = Convert.ToInt32(ddlAcademicStatuses.SelectedValue)
End If
If ddlAcademicMotives.SelectedValue <> "-1" Then
motive = Convert.ToInt64(ddlAcademicMotives.SelectedValue)
End If
If ddlTerms.SelectedValue <> "-2" Then
term = Convert.ToInt64(ddlTerms.SelectedValue)
End If
If ddlYears.SelectedValue <> "-2" Then
year = Convert.ToInt32(ddlYears.SelectedValue)
End If
ParametrosRpt.Add("NombreReporte", "grades_report_horizontal")
ParametrosRpt.Add("PaginaAnterior", Request.ServerVariables("URL"))
ParametrosRpt.Add("status", status)
ParametrosRpt.Add("motive", motive)
ParametrosRpt.Add("term", term)
ParametrosRpt.Add("year", year)
Session("ParametrosRpt") = ParametrosRpt
Response.Redirect("~/desarrollo/Reportes/Reportes.aspx", False)
End Sub
Convert.ToInt32 junto a tipos anulables cuando proceses parámetros provenientes de interfaces web; esto previene errores de tipo y asegura la integridad de los datos enviados a la capa de persistencia.