none
Problema con ExecuteReader()

    Pregunta

  • Hola a todos. Soy nuevo en esto de programando en visual studio. Resulta que me gustaría crear una aplicación de escritorio que conecte con un archivo excel como base de datos y que sea capaz de realizar las mismas funciones de select, insert y delete que hace SQL. Sé que debería usar alguna base de datos tipo SQL, pero en este caso no es posible ya que la decisión no pasa por mi.

    Tengo un código que está vinculado a un textbox. Lo que quiero que pase es que cuando el usuario ingresa un RUT (ej: 12210964K), este lo busque en la hoja correspondiente. Si el RUT existe, entonces que en otros textbox me entregue el nombre y si está activo o inactivo. En caso de que el RUT no exista, que no haga nada.

    Aquí he tenido dos problemas. El primero es con el comando ExecuteReader(). Cuando ingreso un RUT que sólo contiene dígitos, funciona como debe de ser, pero si tiene una "K" me dice "Excepción no controlada del tipo 'System.Data.OleDb.OleDbException' en System.Data.dll". Este error pasa siempre que el ExecuteReader() recibe una letra.

    El segundo problema, es que no logro hacer que cuando el RUT no existe no haga nada y me arroja el mismo error.

    A continuación, les dejo las declaraciones y el código que estoy utilizando para ver si me pueden echar una mano.

        Dim cn As New OleDb.OleDbConnection
        Dim cm As New OleDb.OleDbCommand
        Dim da As New OleDb.OleDbDataAdapter
        Dim dt As New DataTable
        Dim k As Double
        Dim rut_pers As String
        Dim rut As String
        Dim estado As String
        Dim exc As OleDb.OleDbException
        Dim reader As OleDb.OleDbDataReader
    
    
    Private Sub TextBox1_LostFocus(sender As Object, e As EventArgs) Handles TextBox.LostFocus
    
           
            rut = TextBox.Text
    
            cn.Open()
            cm.Connection = cn
            cm.CommandText = "select count(*) from [dias acum$] where rut_pes = " & rut
            reader = cm.ExecuteReader()
    
            reader.Read()
    
            If reader(0) = 0 Then
                estado = "Activo"
                TextBox5.Text = estado
    
                reader.Close()
                cn.Close()
    
            ElseIf reader(0) > 0 Then
                cm.CommandText = "select nombre, estado from [dias acum$] where rut_pers = " & rut
                reader = cm.ExecuteReader()
                reader.Read()
                TextBox4.Text = reader(0)
                If reader(1) = 1 Then
                    estado = "Activo"
                ElseIf reader(1) = 0 Then
                    estado = "Inactivo"
                End If
                TextBox5.Text = estado
                
                reader.Close()
                cn.Close()
            End If
    
        End Sub
    
    
    

    De antemano, muchas gracias.

    miércoles, 22 de marzo de 2017 15:07

Respuestas

  • ppsev,

    Te recomiendo no declarar variables a nivel de clase y parametrizar la consulta:

    Dim rut As String = TextBox1.Text
    
    Try
    	Using cn As New OleDbConnection("Cadena de conexión")
    
    		Dim ConsultaSQL = "SELECT nombre, estado FROM [dias acum$] WHERE rut_pers = @rut_pers"
    
    		Dim cmd As New OleDbCommand(ConsultaSQL, cn)
    
    		cmd.Parameters.AddWithValue("@rut_pers", rut)
    
    		cn.Open() 'Abrir conexión
    
    		Dim reader As OleDbDataReader = cmd.ExecuteReader()
    
    		If reader.HasRows Then '¿Existen filas?
    			TextBox4.Text = reader(0)
    			TextBox5.Text = If(reader(1) = 1, "Activo", "Inactivo")
    		Else
    			TextBox4.Text = String.Empty
    			TextBox5.Text = String.Empty
    		End If
    
    		reader.Close()
    	End Using
    Catch ex As Exception
    	MessageBox.Show(ex.Message)
    End Try


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    miércoles, 22 de marzo de 2017 17:12

Todas las respuestas

  • Saludos:

    Lo que puedes hacer es enviar el requerimiento como string, asi:

    cm.CommandText = "select count(*) from [dias acum$] where rut_pes = '" & rut &"' "
    
            
    cm.CommandText = "select nombre, estado from [dias acum$] where rut_pers = '" & rut & "' "
    

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    miércoles, 22 de marzo de 2017 15:22
  • Saludos:

    Lo que puedes hacer es enviar el requerimiento como string, asi:

    cm.CommandText = "select count(*) from [dias acum$] where rut_pes = '" & rut &"' "
    
            
    cm.CommandText = "select nombre, estado from [dias acum$] where rut_pers = '" & rut & "' "

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    Hola Jose Luis,

    Probé lo que sugeriste, pero no dio resultado. Me entregó este error en "reader = cm.ExecuteReader()": 

    "Excepción no controlada del tipo 'System.Data.OleDb.OleDbException' en System.Data.dll

    Información adicional: No se han especificado valores para algunos de los parámetros requeridos."
    miércoles, 22 de marzo de 2017 15:29
  • Saludos:

    Acabo de darme cuenta que estas abriendo la conexion ANTES de declararla y asignar el command.

    Te paso un ejemplo:

    Using connection As OleDbConnection = New OleDbConnection( _  
      "Provider=MSDataShape;Data Provider=SQLOLEDB;" & _  
      "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")  
      
    Dim custCMD As OleDbCommand = New OleDbCommand( _  
      "SHAPE {SELECT CustomerID, CompanyName FROM Customers} " & _  
      "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS CustomerOrders " & _  
      "RELATE CustomerID TO CustomerID)", connection)  
    connection.Open()  
      
    Dim custReader As OleDbDataReader = custCMD.ExecuteReader()  
    Dim orderReader As OleDbDataReader  
      
    Do While custReader.Read()  
      Console.WriteLine("Orders for " & custReader.GetString(1))   
      ' custReader.GetString(1) = CompanyName  
      
      orderReader = custReader.GetValue(2)  
      ' custReader.GetValue(2) = Orders chapter as DataReader  
      
      Do While orderReader.Read()  
        Console.WriteLine(vbTab & orderReader.GetInt32(1))  
        ' orderReader.GetInt32(1) = OrderID  
      Loop  
      orderReader.Close()  
    Loop  
    ' Make sure to always close readers and connections.  
    custReader.Close()  
    End Using  
    

    1) Primero se declara la conexion.

    2) Asignas el Command.

    3) Abres la conexion

    4) declaras y ejecutas el Reader

    5) Lees el resultado.

    Aqui el link:

    https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    • Propuesto como respuesta Jose Luis Vargas miércoles, 22 de marzo de 2017 16:44
    • Votado como útil ppsev miércoles, 22 de marzo de 2017 18:04
    miércoles, 22 de marzo de 2017 16:44
  • ppsev,

    Te recomiendo no declarar variables a nivel de clase y parametrizar la consulta:

    Dim rut As String = TextBox1.Text
    
    Try
    	Using cn As New OleDbConnection("Cadena de conexión")
    
    		Dim ConsultaSQL = "SELECT nombre, estado FROM [dias acum$] WHERE rut_pers = @rut_pers"
    
    		Dim cmd As New OleDbCommand(ConsultaSQL, cn)
    
    		cmd.Parameters.AddWithValue("@rut_pers", rut)
    
    		cn.Open() 'Abrir conexión
    
    		Dim reader As OleDbDataReader = cmd.ExecuteReader()
    
    		If reader.HasRows Then '¿Existen filas?
    			TextBox4.Text = reader(0)
    			TextBox5.Text = If(reader(1) = 1, "Activo", "Inactivo")
    		Else
    			TextBox4.Text = String.Empty
    			TextBox5.Text = String.Empty
    		End If
    
    		reader.Close()
    	End Using
    Catch ex As Exception
    	MessageBox.Show(ex.Message)
    End Try


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.
    miércoles, 22 de marzo de 2017 17:12
  • ppsev,

    Te recomiendo no declarar variables a nivel de clase y parametrizar la consulta:

    Dim rut As String = TextBox1.Text
    
    Try
    	Using cn As New OleDbConnection("Cadena de conexión")
    
    		Dim ConsultaSQL = "SELECT nombre, estado FROM [dias acum$] WHERE rut_pers = @rut_pers"
    
    		Dim cmd As New OleDbCommand(ConsultaSQL, cn)
    
    		cmd.Parameters.AddWithValue("@rut_pers", rut)
    
    		cn.Open() 'Abrir conexión
    
    		Dim reader As OleDbDataReader = cmd.ExecuteReader()
    
    		If reader.HasRows Then '¿Existen filas?
    			TextBox4.Text = reader(0)
    			TextBox5.Text = If(reader(1) = 1, "Activo", "Inactivo")
    		Else
    			TextBox4.Text = String.Empty
    			TextBox5.Text = String.Empty
    		End If
    
    		reader.Close()
    	End Using
    Catch ex As Exception
    	MessageBox.Show(ex.Message)
    End Try


    Espero que la información proporcionada te haya sido de utilidad, quedo atento a tus comentarios.

    Esto me sirvió de mucho. Lo que si, cuando consulto por un RUT terminado en K me dice "No coinciden los tipos de datos en la expresión de criterios."

    Otra cosa, qué es declarar variables a nivel de clase y parametrizar la consulta?

    Saludos y gracias.

    miércoles, 22 de marzo de 2017 18:03
  • Saludos:

    Acabo de darme cuenta que estas abriendo la conexion ANTES de declararla y asignar el command.

    Te paso un ejemplo:

    Using connection As OleDbConnection = New OleDbConnection( _  
      "Provider=MSDataShape;Data Provider=SQLOLEDB;" & _  
      "Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind")  
      
    Dim custCMD As OleDbCommand = New OleDbCommand( _  
      "SHAPE {SELECT CustomerID, CompanyName FROM Customers} " & _  
      "APPEND ({SELECT CustomerID, OrderID FROM Orders} AS CustomerOrders " & _  
      "RELATE CustomerID TO CustomerID)", connection)  
    connection.Open()  
      
    Dim custReader As OleDbDataReader = custCMD.ExecuteReader()  
    Dim orderReader As OleDbDataReader  
      
    Do While custReader.Read()  
      Console.WriteLine("Orders for " & custReader.GetString(1))   
      ' custReader.GetString(1) = CompanyName  
      
      orderReader = custReader.GetValue(2)  
      ' custReader.GetValue(2) = Orders chapter as DataReader  
      
      Do While orderReader.Read()  
        Console.WriteLine(vbTab & orderReader.GetInt32(1))  
        ' orderReader.GetInt32(1) = OrderID  
      Loop  
      orderReader.Close()  
    Loop  
    ' Make sure to always close readers and connections.  
    custReader.Close()  
    End Using  
    

    1) Primero se declara la conexion.

    2) Asignas el Command.

    3) Abres la conexion

    4) declaras y ejecutas el Reader

    5) Lees el resultado.

    Aqui el link:

    https://msdn.microsoft.com/en-us/library/haa3afyz(v=vs.110).aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    Gracias Jose Luis. Resulta que la conexión con el libro de excel estaba declarado de antes y se ejecuta cuando abro el archivo.

    Saludos.

    miércoles, 22 de marzo de 2017 18:05
  • Saludos:

    Podrias usar la siguiente sintaxis:

    cm.CommandText = "select count(*) from [dias acum$] where rut_pes LIKE '%" & rut &"%' "
    
            
    cm.CommandText = "select nombre, estado from [dias acum$] where rut_pers LIKE '%" & rut & "%' 

    Para la declaracion de variables te suguiero leas acerca de herencia y variables.

    Espero ayude.

    JOSE LUIS


    Dios NO los llamo LAS DIEZ RECOMENDACIONES

    miércoles, 22 de marzo de 2017 18:15