none
Como se soluciona el Error -> Ya hay un DataReader abierto asociado a este comando, debe cerrarlo primero.

    Question

  • Saludos a todos, estoy trabajando con Visual Studio 2005 en aplicaciones para escritorio y mi base de datos es SQL Server 2000, pues bien en mi aplicacion me esta enviando el error "Ya hay un DataReader abierto asociado a este comando, debe cerrarlo primero.".
    Para que se den una idea de lo que estoy haciendo les platico, las opciones de menu que debe presentar el sistema son de acuerdo al usuario que ingrese a el, y estas opciones las toma de una tabla que es donde tengo todas las opciones pertenecientes a cada aplicacion que se desarrolle, de esta forma solo basta con agregar un registro en la tabla y automaticamente aparece la opcion en el sistema sin necesidad de modificar la pantalla principal. Bueno, pues las rutinas las pongo a continuacion para ver si alguien me indica porque genera el error.

        Private Sub MenuPrincipal_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    	'-- Abrir conexion a base de datos
            MiCnxSQL = New SqlConnection(miCadenaDeConexion)
            MiCnxSQL.Open()
            Call sb_CreaMenus(0)
        End Sub
    
        Private Sub sb_CreaMenus(ByVal intPadre As Int32)
            Dim MiMenu As MenuStrip = MenuStrip1, MiSubMenu As ToolStripMenuItem = Nothing
            Dim strDesc As String
            strSQL = "SELECT * FROM BdAdministracion..adm_Menus WHERE Id_Aplicacion = " & intAplicacion & " AND men_Padre = " & intPadre _
                & " AND men_Status = 'A' ORDER BY men_Orden"
            Dim myCommando As New SqlCommand(strSQL, MiCnxSQL)
            Dim drMenu As SqlDataReader = myCommando.ExecuteReader
            Do While drmenu.Read
                If CInt(Mid(strAccesos, drmenu("Id_Menu"), 1)) > 0 Then
                    strDesc = drmenu("men_Descripcion")
                    MiSubMenu = New ToolStripMenuItem(strDesc)
                    Call sb_CreaSubMenus(CInt(drMenu("Id_Menu")), MiSubMenu)
                    MiMenu.MdiWindowListItem = MiSubMenu
                    MiMenu.Items.Add(MiSubMenu)
                    Me.MainMenuStrip = MiMenu
                    Me.Controls.Add(MiMenu)
                End If
            Loop
            drMenu.Close() : drMenu = Nothing
            If MiSubMenu Is Nothing Then
                Beep()
                MessageBox.Show("No tienes acceso al " & Me.Text, "Acceso no autorizado", MessageBoxButtons.OK, MessageBoxIcon.Error)
                clsSeg.CierraConexion()
                Global.System.Windows.Forms.Application.Exit()
                End
            End If
        End Sub
    
        Private Sub sb_CreaSubMenus(ByVal intPadre As Int32, ByRef MenuPadre As ToolStripMenuItem)
            Dim MenuHijo As ToolStripMenuItem = Nothing, MiOpcion As ToolStripMenuItem = Nothing
            Dim strKey As String = String.Empty, strDesc As String = String.Empty, strMiID As String = String.Empty
            strSQL = "SELECT * FROM BdAdministracion..adm_Menus WHERE Id_Aplicacion = " & intAplicacion & " AND men_Padre = " & intPadre & " AND men_Status = 'A' ORDER BY men_Orden"
            Dim myCommandHijo As New SqlCommand(strSQL, MiCnxSQL)
            Dim drHijo As SqlDataReader = myCommandHijo.ExecuteReader
            Do While drHijo.Read
                If CInt(Mid(strAccesos, drHijo("Id_Menu"), 1)) > 0 Then
                    strDesc = drHijo("men_Descripcion")
                    If drHijo("men_Tipo") = "M" Then
                        MenuHijo = New ToolStripMenuItem(strDesc)
                        MenuPadre.DropDownItems.Add(MenuHijo)
                        Call sb_CreaSubMenus(CInt(drHijo("Id_Menu")), MenuHijo)
                    ElseIf drHijo("men_Tipo") = "A" Then
                        strKey = drHijo("men_Nombre")
                        strMiID = drHijo("Id_Menu")
                        MiOpcion = New ToolStripMenuItem(strDesc, Nothing, New EventHandler(AddressOf Menus_Click))
                        MiOpcion.Name = strKey
                        MiOpcion.Tag = strMiID
                        MenuPadre.DropDownItems.Add(MiOpcion)
                    Else
                        Dim MiSeparador As New ToolStripSeparator
                        MenuPadre.DropDownItems.Add(MiSeparador)
                    End If
                End If
            Loop
            drHijo.Close() : drHijo = Nothing
            myCommandHijo.Dispose()
        End Sub
    


    Si en la rutina sb_CreaMenus comento la linea -> Call sb_CreaSubMenus(CInt(drMenu("Id_Menu")), MiSubMenu)
    mi aplicacion funciona correctamente pero al habilitar esta linea se genera el error el entrar la primera vez a la rutina, espero que alguien me pueda explicar porque de este error y como solucionarlo. He realizado varias versiones tanto de la conexion a la BD como de la programacion y una solucion es abrir y cerrar la conexion pero esto hace que sea super lenta la aplicacion, tambien lo he realizado con las librerias ADO como lo hacien en Visual Basic 6 y procesa rapidisimo pero no creo que sea la solucion pues es utilizar objetos de VB6. Bueno espero sus respuestas

    Friday, March 05, 2010 4:36 PM

Answers

All replies

  • mientras creas el menú, mantienes el datareader donde cargas los menus abierto, y entonces llamas para crear los submenus con otro datareader... es normal te falle, el datareader te bloquea la conexión hasta que lo liberas, no podrás abrir otro...

    Lo mejor es que lo cargues todo en tables y luego recorras las tablas sin datareaders...
    Iván Noya Cendal
    http://www.seuvella.com

    Si la respuesta te ha ayudado, marcala.
    • Marked as answer by Paco Miranda Friday, March 05, 2010 5:25 PM
    Friday, March 05, 2010 4:44 PM
  • hola

    si habilitas MARS en tu connection string podras hacer uso de datareader anidados

    Want to Execute Multiple Queries on a Single Connection? Go to MARS


    como veras es tan simple como agregar esta config en el string de conexion

    saludos
    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    Friday, March 05, 2010 4:51 PM
  • Gracias por sus respuestas, con tu comentario IncaSoft ahora entiendo por que lo del error, bien tendre que utilizar Tablas y espero no encontrarme con otra sorpresita. Por otro lado Leandro los de MARS se ve bastante bien pero segun lo que lei en las ligas solo es para SQL Server 2005 y yp tengo el SQL Sever 2000 asi que tendre que hacer mas talacha pero bueno asi es como se aprenden estas cosas.

    Buen dia y nuevamente gracias.

    Friday, March 05, 2010 5:25 PM
  • Hola,

    me topé con el mismo problema y lo solucioné utilizando un DataTable. Es sencillo. Un ejemplo a groso modo sería:

    Dim Cmd as New SqlCommand("Select ....", Conexion)
    Dim CmdUpdate as New SqlCommand("Update ....", Conexion)
    Dim dt as New DataTable
    
    dt.TableName="Tabla"
    dt.Load(Cmd.ExecuteReader)
    
    For Each Fila As DataRow in dt.Rows
      'Ejecutar el update con un SQLCommand para cada fila
      CmdUpdate.ExecuteNonQuery
    Next
    
    dt = Nothing
    Cmd = Nothing
    CmdUpdate = Nothing
    

    Un Saludo.

    Thursday, December 30, 2010 10:48 AM
  • Muchas Gracias por el aporte Leandro, me ha servido y me evitaste mucha talacha

    Saludos

    Thursday, June 14, 2012 12:16 AM