¿Cómo capturo los datos de un SqlDataReader que están en una clase en una función?

publicado por: Anonymous

Estoy trabajando con vb.net y en la clase conexion tengo el siguiente método:

Function consulta()

Try
    conectar()
    comando = conexion.CreateCommand()
    comando.CommandText = "select * from persona"

    reader = comando.ExecuteReader()
Catch ex As Exception
    MsgBox("Error 1 " + ex.ToString)
End Try

desconectar()

Return reader
End Function

El objeto reader es de tipo SqlDataReader.

Lo que necesito no es introducir los resultados en un DataGrid, sino llamarlos desde el formulario y mostrar cada campo en un TextBox. Por ejemplo el campo nombre introducirlo en un TextBox, el apellido en otro TextBox.

solución

Hay 2 problemas muy serios y fundamentales en el diseño actual que tienes y que las otras respuestas no han mencionado:

  1. Estás empleando variables globales para la conexión y el SqlDataReader.
  2. Estás cerrando la conexión (desconectar()) antes de devolver el SqlDataReader, de modo que cuando trates de leer los datos con el SqlDataReader, te va a lanzar excepciones.

Vez tras vez estoy viendo preguntas donde se está usando ese patrón de emplear conexiones globales. Esto es muy mala práctica y te va a causar problemas en programas mas serios. No hay nada malo en centralizar el código que abre la conexión. Pero no es correcto de guardar la conexión en una variable global.

Y el problema con el segundo punto es que para poder devolver un SqlDataReader y poder seguir usándolo, la conexión debe quedar abierta. Pero si quitas la llamada desconectar() de tu método para arreglar este problema, ahora tu código se pone aún mas frágil de lo que ya es, porque no queda muy claro quién tiene la responsabilidad de cerrar la conexión.

Aquí te dejo un patrón mucho más solido y reutilizable que puedes emplear para leer los datos de un SqlDataReader para cualquier consulta y que no cae en los problemas de diseño mencionados arriba.

Para el ejemplo que te comparto, voy a asumir que en vez de tener un método conectar() que abre una conexión y la asigna a una variable global (a evitar), mas bien voy a asumir que has definido un método CrearConexion que simplemente devuelve una nueva instancia de SqlConnection sin asignarla a una variable global (correcto). Algo como:

Public Function CrearConexion() As SqlConnection
    Return New SqlConnection("<cadena de conexión>")
End Function

Método EjecutarLeerConsulta:

Public Sub EjecutarLeerConsulta(
    sql As String,
    leerRegistro As Action(Of SqlDataReader),
    ParamArray parametros As SqlParameter())

    Using conn As SqlConnection = CrearConexion()
        Using cmd = New SqlCommand(sql, conn)
            cmd.Parameters.AddRange(parametros)
            conn.Open()

            Using reader As SqlDataReader = cmd.ExecuteReader()
                While (reader.Read())
                    leerRegistro(reader)
                End While
            End Using
        End Using
    End Using
End Sub

Con este método, puedes ejecutar y leer cualquier consulta usando las mejores prácticas, sin variables globales, sin tener que preocuparte de cuando abrir y cerrar la conexión, etc. Todo está manejado automáticamente en este método central.

Cómo usarlo

Para usar el método, necesitas pasarle por lo menos 2 parámetros:

  • La cadena SQL.
  • Una expresión lambda que define el código que debe ejecutarse para cada registro devuelto por la consulta.
  • (Opcional) Una lista de parámetros (SqlParameter) si la consulta las necesita.

Ejemplo:

EjecutarLeerConsulta(
    "select * from persona",
    Sub(reader)
        Dim nombre As String = reader("nombre")
        Dim apellido As String = reader("apellido")
        ' agrega código aquí que asigna los valores a los TextBox o lo que quieras.
    End Sub)

Y si necesitas armar consultas con parámetros, la llamada se vería así:

EjecutarLeerConsulta(
    "select * from persona where nombre = @nombre and apellido = @apellido",
    Sub(reader)
        Dim nombre As String = reader("nombre")
        Dim apellido As String = reader("apellido")
        ' agrega código aquí que asigna los valores a los TextBox o lo que quieras.
    End Sub,
    New SqlParameter("@nombre", "John"),
    New SqlParameter("@apellido", "Smith"))
Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *