none
Instrucciones Básicas en BD SQL Server

    Pregunta

  • Buenos días y gracias por entrar. Soy novato en base de datos y para hacer un programa de gestión quiero primero ir practicando los aspectos básicos.

    Para no hacer necesidad de usar ningún tipo de servidor, en Herramientas > Conectar con la base de datos elegí como origen de datos "archivo de base de datos de SQL Server" y cree una nueva bd, la copié y la pegué en la ruta de la aplicación. Seguido copié la cadena de conexión para hacer todo manual así aprender.

    Formulario

    Lo que quiero lograr es, desde el botón conectar, valga la redundancia, conectarme y lo mismo con los demás botones, y para eso busque guías y ayudas en foros pero no logré mas que conectarme a la base de datos.

    La base de datos tiene una tabla llamada Controles y una sola columna llamada Cantidad como int

    Para conectarme use:

        Dim cConexion As New SqlClient.SqlConnection
        Dim path As String = Application.StartupPath + "\db.mdf"
        Dim Adaptador As New SqlClient.SqlDataAdapter
        Dim DSet As New DataSet
        Dim dr As SqlDataReader
    
        Private Sub btnConectar_Click(sender As Object, e As EventArgs) Handles btnConectar.Click
            Try
               
                cConexion.ConnectionString = ("Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=" + path + ";Integrated Security=True;Connect Timeout=30")
                cConexion.Open()
                
            Catch ex As Exception
                
                MsgBox("Error " + ex.Message)
               
            End Try
        End Sub

    Para el botón Mostrar (me da como error "Error de lectura porque no hay datos.")

     Private Sub btnMostrar_Click(sender As Object, e As EventArgs) Handles btnMostrar.Click
            Try
                Dim Sql As String = "SELECT Cantidad FROM Controles"
                Dim cmd As New SqlCommand(Sql, cConexion)
                dr = cmd.ExecuteReader
                TextBox1.Text = dr("Cantidad").ToString
                dr.Close()
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
    
            End Try
        End Sub

    Y para el botón Insertar/Actualizar (no da error pero supongo que igual no funciona):

    Private Sub btnInAct_Click(sender As Object, e As EventArgs) Handles btnInAct.Click
            Try
                Dim Sql As String = "INSERT INTO Controles (Cantidad) VALUES (@Cantidad)"
                Dim cmd As New SqlCommand(Sql, cConexion)
                cmd.Parameters.AddWithValue("@Cantidad", TextBox1.Text)
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
        End Sub

    ¿Qué estoy haciendo mal? 

    Desde ya muchisimas gracias por el tiempo!

    sábado, 1 de octubre de 2016 22:58

Respuestas

  • Hola SalvadorB,

    Tu error se produce porque no usas la función Read() del SqlDataReader, por lo que nunca lees los valores. Además si solo necesitas un valor debes usar ExecuteScalar.

    Recomendaría usas esta estructura en tu código :

        Private Sub btnMostrar_Click(sender As Object, e As EventArgs) Handles btnMostrar.Click
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim Sql As String = "SELECT Cantidad FROM Controles where id = 1"
                    Dim cmd As New SqlCommand(Sql, con)
    
                    TextBox1.Text = CStr(cmd.ExecuteScalar)
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
        End Sub

    Pruébalo y comentas como te va.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI


    sábado, 1 de octubre de 2016 23:07
  • Hola de nuevo SalvadorB,

    Me olvidé del otro código disculpa.

       Private Sub btnInAct_Click(sender As Object, e As EventArgs) Handles btnInAct.Click
    
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim Sql As String = "INSERT INTO Controles (Cantidad) VALUES (@Cantidad)"
                    Dim cmd As New SqlCommand(Sql, con)
                    cmd.Parameters.AddWithValue("@Cantidad", TextBox1.Text)
    
                    'Ejecuta la consulta
                    cmd.ExecuteNonQuery()
    
                    MessageBox.Show("Registrado!!")
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
    
        End Sub

    En tu código no ejecutabas la consulta, por lo que nunca te lo iva a guardar en la BD.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta SalvadorB sábado, 1 de octubre de 2016 23:16
    sábado, 1 de octubre de 2016 23:11
  • Hola SalvadorB,

    También es correcto, no obstante te dejo algunas consideraciones :)

    Pero tendrías que hacer uso de la función Trim(..) ya que si te das cuenta en cada bucle del While agregas el valor y un espacio en blanco y el último valor no es la excepción. (sería más notorio si cambias por un separador como una coma, resultado = valor1,valor2,valor3,)

      While dr.Read
          cad += CStr(dr(0)) + Space(1)
      End While
      TextBox1.Text = cad.Trim()

    Aunque no es malo usar cadenas, también hay funciones que nos pueden ayudar. El Space(valor) genera un número de espacios en blanco según el valor dado.

    TextBox1.Text = "" es igual a TextBox1.Text = String.Empty

    Y para evitar la concatenación entre cadenas usando el + :

    String.Format("Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={0};
                       Integrated Security=True;Connect Timeout=30", path)

    Dónde el {0} será reemplazado por el valor que devuelva la variable path.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta SalvadorB domingo, 2 de octubre de 2016 0:47
    domingo, 2 de octubre de 2016 0:33

Todas las respuestas

  • Hola SalvadorB,

    Tu error se produce porque no usas la función Read() del SqlDataReader, por lo que nunca lees los valores. Además si solo necesitas un valor debes usar ExecuteScalar.

    Recomendaría usas esta estructura en tu código :

        Private Sub btnMostrar_Click(sender As Object, e As EventArgs) Handles btnMostrar.Click
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim Sql As String = "SELECT Cantidad FROM Controles where id = 1"
                    Dim cmd As New SqlCommand(Sql, con)
    
                    TextBox1.Text = CStr(cmd.ExecuteScalar)
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
        End Sub

    Pruébalo y comentas como te va.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI


    sábado, 1 de octubre de 2016 23:07
  • Hola de nuevo SalvadorB,

    Me olvidé del otro código disculpa.

       Private Sub btnInAct_Click(sender As Object, e As EventArgs) Handles btnInAct.Click
    
            Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim Sql As String = "INSERT INTO Controles (Cantidad) VALUES (@Cantidad)"
                    Dim cmd As New SqlCommand(Sql, con)
                    cmd.Parameters.AddWithValue("@Cantidad", TextBox1.Text)
    
                    'Ejecuta la consulta
                    cmd.ExecuteNonQuery()
    
                    MessageBox.Show("Registrado!!")
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
    
        End Sub

    En tu código no ejecutabas la consulta, por lo que nunca te lo iva a guardar en la BD.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta SalvadorB sábado, 1 de octubre de 2016 23:16
    sábado, 1 de octubre de 2016 23:11
  • Genial!, funciona perfecto, sin embargo supongo que es porque el boton insertar lo que hace es añadir nuevas filas en vez de editar la primera, y el ExecuteScalar lee solo el primer registro no? Como tendría que hacer si quisiera editar siempre la primera fila?

    Y para leer todas las filas en el textbox uso un execute normal y se lo voy concatenando a un string y despues le doy ese valor al text del textbox?

    sábado, 1 de octubre de 2016 23:19
  • Hola SalvadorB,

    [-] ... porque el boton insertar lo que hace es añadir nuevas filas en vez de editar la primera ..

    Claro, ya que en tu query (consulta) haces uso del INSERT INTO el cual almacenará un nuevo registro a la BD, pero si cambiaras la consulta a un UPDATE lo que harías es actualizar "X" registro.

    - Para actualizar un registro es similar :

      Dim Sql As String = "UPDATE Controles SET Cantidad = @cant WHERE id = @id"
      Dim cmd As New SqlCommand(Sql, con)
      cmd.Parameters.AddWithValue("@cant", TextBox1.Text)
      cmd.Parameters.AddWithValue("@id", 1)
    
      'Ejecuta la consulta
       cmd.ExecuteNonQuery()

    Dónde, el registro con el ID = 1 actualizará su valor por el contenido del TextBox1.Text.

    [-] ... ExecuteScalar lee solo el primer registro no?

    No, el ExecuteScalar devuelve el valor de la primera columna de la primera fila de una consulta. Es decirdevuelve el valor de un solo campo.

    SELECT Cantidad FROM Controles where id = 1           <= Aplica
    SELECT Cantidad, Precio FROM Controles where id = 1   <= NO aplica, usarías el SQLDataReader

    Método SqlCommand.ExecuteScalar ()

    [-] ... Y para leer todas las filas en el textbox uso un execute normal y se lo voy concatenando a un string y despues le doy ese valor al text del textbox

    Puedes hacer :

          Try
                Using con As New SqlConnection("MiCadenaConexion")
                    con.Open()
    
                    Dim Sql As String = "SELECT Cantidad FROM Controles"
                    Dim cmd As New SqlCommand(Sql, con)
    
                    Dim dr As SqlDataReader = cmd.ExecuteReader
    
                    'Almacenarpa los valores
                    Dim datos As New List(Of String)
                    'Si hay filas
                    If dr.HasRows Then
                        While dr.Read()
                            datos.Add(CStr(dr("Cantidad")))
                        End While
                    End If
    
                    'Agrega el resultado de cada campo
                    'Separados por comas (,)
                    TextBox1.Text = String.Join(",", datos)
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    sábado, 1 de octubre de 2016 23:41
  • Muchas gracias Joel, entendí todo. También me aventuré a hacer lo de leer todas las filas y salió

    Private Sub btnMostrar_Click(sender As Object, e As EventArgs) Handles btnMostrar.Click
            TextBox1.Text = ""
            cad = ""
            Try
                Using con As New SqlConnection("Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename=" + path + ";Integrated Security=True;Connect Timeout=30")
                    con.Open()
    
                    Dim Sql As String = "SELECT Cantidad FROM Controles"
                    Dim cmd As New SqlCommand(Sql, con)
                    dr = cmd.ExecuteReader
                    While dr.Read
                        cad = cad + CStr(dr(0)) + " "
                    End While
                    TextBox1.Text = cad
                    'TextBox1.Text = CStr(cmd.ExecuteScalar)
                End Using
            Catch ex As Exception
                MsgBox("Error: " + ex.Message)
            End Try
        End Sub

    sábado, 1 de octubre de 2016 23:47
  • Hola SalvadorB,

    También es correcto, no obstante te dejo algunas consideraciones :)

    Pero tendrías que hacer uso de la función Trim(..) ya que si te das cuenta en cada bucle del While agregas el valor y un espacio en blanco y el último valor no es la excepción. (sería más notorio si cambias por un separador como una coma, resultado = valor1,valor2,valor3,)

      While dr.Read
          cad += CStr(dr(0)) + Space(1)
      End While
      TextBox1.Text = cad.Trim()

    Aunque no es malo usar cadenas, también hay funciones que nos pueden ayudar. El Space(valor) genera un número de espacios en blanco según el valor dado.

    TextBox1.Text = "" es igual a TextBox1.Text = String.Empty

    Y para evitar la concatenación entre cadenas usando el + :

    String.Format("Data Source=(LocalDB)\MSSQLLocalDB;AttachDbFilename={0};
                       Integrated Security=True;Connect Timeout=30", path)

    Dónde el {0} será reemplazado por el valor que devuelva la variable path.

    Saludos.


    JC NaupaCrispín
    Lima - Perú

    La magia no existe, la programación SI

    • Marcado como respuesta SalvadorB domingo, 2 de octubre de 2016 0:47
    domingo, 2 de octubre de 2016 0:33
  • Muchas gracias por los tips Joel, se nota que la tenés clara en el lenguaje ;) saludos
    domingo, 2 de octubre de 2016 0:50