DevOps & Development 4 min de lectura 30 de agosto de 2025

Revisión estructura código

Optimiza tu código en VB.NET migrando de Hashtable a Dictionary y usando tipos anulables para manejar valores NULL en MSSQL.

Solución en "Dos Clics" (TL;DR)

Revisión y optimización de estructura en VB.NET, recomendando el paso de Hashtable a Dictionary y el uso de tipos anulables para un correcto manejo de valores NULL en bases de datos.

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:

Visual Basic (VB.NET)
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 caso 0) 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, Hashtable almacena elementos como Object requiriendo operaciones de boxing/unboxing. En .NET moderno es preferible utilizar Dictionary(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 índice Session("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.

Riesgo con tipos primitivos: Si omites la asignación en un 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.

Visual Basic (VB.NET - Versión Optimizada)
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
Consejo Práctico: Utiliza conversiones explícitas como 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.