Ya hay un DataReader abierto asociado a este comando, debe cerrarlo primero


Normalmente lo que hago para leer una tabla es utilizar un objeto SQLDataReader. Me tiene pasado en alguna aplicación la necesidad de ejecutar un Update dentro del bucle de lectura. Al estar abierto el SQLDataReader salta el error «Ya hay un DataReader abierto asociado a este comando, debe cerrarlo primero».

Para solucionarlo empleo un objeto DataTable que nos sirve igual que el DataReader. Un ejemplo de uso sería:

Dim Cmd As New SQLCommand("Select a, b, c, d from Tabla", Conexion)
Dim dt As New DataTable

dt.TableName = 'Tabla'
dt.Load(Cmd.ExecuteReader)

For Each Fila As DataRow In dt.Rows
'Ahora se puede utilizar una consulta SQL sin que dé el error del DataReader
Next


dt = Nothing
Cmd = Nothing

Espero que le sirva a alguien. Un saludo.

Autor: toniogago

Auxiliar Técnico en Informática de Gestión.

2 opiniones en “Ya hay un DataReader abierto asociado a este comando, debe cerrarlo primero”

  1. Hola a mi me aparece el mismo error , ojala pudieras ayudarme este el código:

     Dim vdesp As String
            v_fila.Connection = dbSanciones
            v_fila.CommandType = CommandType.Text
            v_SQLmostrar = "SELECT Area FROM Jefes WHERE Id_Jefe=  '" & CmbArea07.SelectedValue & "'"
    
            dbSanciones.Open()
            'v_fila.CommandText = v_SQLmostrar
            'v_reg = v_fila.ExecuteReader
    
            v_fila.CommandText = v_SQLmostrar
            v_reg = v_fila.ExecuteReader()
            Do While v_reg.Read
                vareacombo = v_reg(0).ToString.Trim
                'MsgBox(v_reg(0)) 
    
                vdesp = "Despacho del Títular"
                MsgBox(vdesp)
    
                ' MsgBox(vareacombo)
    
                Select Case vdesp
                    Case "Despacho del Títular"
                        LlamarDatos("Select  Personal.Num_nom,Num_Inv as No_Inv,Descrip As Nombre,Marca,Modelo,Num_Serie,EdoFisico As Estado_Fisico,Obser AS Datos_Comple,Personal.Nombre+Personal.Apat+Amat As Responsable,Ubicacion " & _
                                                   " FROM BM  INNER JOIN Asig_Personal ON Asig_Personal.Num_Bm=BM.Num_Bm  " & _
                                                   " INNER JOIN Personal ON Asig_Personal.Num_nom=Personal.Num_nom " & _
                                                   "  INNER JOIN JEFES as j ON (j.Id_Jefe=Personal.Jefe1 Or j.Id_Jefe=Personal.Jefe2 Or j.Id_Jefe=Personal.Jefe3 Or j.Id_Jefe=Personal.Jefe4 Or j.Id_Jefe=Personal.Jefe5)" & _
                                                   "  INNER JOIN Catalogo_BM  ON BM.Id_mod = Catalogo_BM.Id_mod " & _
                                                   " Where  j.Id_Jefe=  '0' and  not Catalogo_Bm.Id_mod in (83,12,7,38,202,260,272,294,122,259) and Personal.Jefe5='0'  and Fec_fin='1900/01/01' order by Responsable")
    
                        Datab = New DataTable
                        Datadap.Fill(Datab)
                        DG07.DataSource = Datab
                        DG07.Columns(0).Visible = False
                End Select
               
    
            Loop
            dbSanciones.Close()
            v_reg.Close()
    

    El error me lo marca señalando la linea:
    Datadap.Fill(Datab)

    Por tu ayuda Gracias!!!

    1. Hora Bere,
      en vez de utilizar un DataReader procura utilizar un DataTable para recorrer la consulta que necesites.

      prueba con este código:

              Dim vdesp As String
              v_fila.Connection = dbSanciones
              v_fila.CommandType = CommandType.Text
              v_SQLmostrar = "SELECT Area FROM Jefes WHERE Id_Jefe=  '" & CmbArea07.SelectedValue & "'"
      
              dbSanciones.Open()
              'v_fila.CommandText = v_SQLmostrar
              'v_reg = v_fila.ExecuteReader
      
              v_fila.CommandText = v_SQLmostrar
      
              Dim jefes As DataTable = New DataTable("Jefes")
              jefes.Load(v_fila.ExecuteReader())
      
              For Each v_reg As DataRow In jefes.Rows
      
                  vareacombo = v_reg(0).ToString.Trim
                  'MsgBox(v_reg(0)) 
      
                  vdesp = "Despacho del Títular"
                  MsgBox(vdesp)
      
                  ' MsgBox(vareacombo)
      
                  Select Case vdesp
                      Case "Despacho del Títular"
                          LlamarDatos("Select  Personal.Num_nom,Num_Inv as No_Inv,Descrip As Nombre,Marca,Modelo,Num_Serie,EdoFisico As Estado_Fisico,Obser AS Datos_Comple,Personal.Nombre+Personal.Apat+Amat As Responsable,Ubicacion " & _
                                                     " FROM BM  INNER JOIN Asig_Personal ON Asig_Personal.Num_Bm=BM.Num_Bm  " & _
                                                     " INNER JOIN Personal ON Asig_Personal.Num_nom=Personal.Num_nom " & _
                                                     "  INNER JOIN JEFES as j ON (j.Id_Jefe=Personal.Jefe1 Or j.Id_Jefe=Personal.Jefe2 Or j.Id_Jefe=Personal.Jefe3 Or j.Id_Jefe=Personal.Jefe4 Or j.Id_Jefe=Personal.Jefe5)" & _
                                                     "  INNER JOIN Catalogo_BM  ON BM.Id_mod = Catalogo_BM.Id_mod " & _
                                                     " Where  j.Id_Jefe=  '0' and  not Catalogo_Bm.Id_mod in (83,12,7,38,202,260,272,294,122,259) and Personal.Jefe5='0'  and Fec_fin='1900/01/01' order by Responsable")
      
                          Datab = New DataTable
                          Datadap.Fill(Datab)
                          DG07.DataSource = Datab
                          DG07.Columns(0).Visible = False
                  End Select
      
      
              Next
              dbSanciones.Close()
              v_reg.Close()
      

      puede que te haga falta importar el espacio de nombres System.Data

Replica a toniogago Cancelar la respuesta