none
problema con the connectionstring property has not been initialized RRS feed

  • Pregunta

  • Buen día, en una aplicación en VB sobre VS2010 logro que al cargar el formulario se llame a una función llamada cargardatos que llena un DGV y que añada dinámicamente una columna con checkbox.

    Luego tengo un botón que según las filas que tengan check en el checkbox entonces las manda a eliminar y luego vuelve a llamar a la funcion cargardatos para de nuevo cargar información en el DGV con la columna checkbox creada dinamicamente.

    Mi problema es que uso una cadena de conexión con la cual no tengo problemas al cargar por primeva vez los datos en el DGV, pero al querer eliminar las filas seleccionas según un check en la columna checkbox me aparece este error:

    the connectionstring property has not been initialized

    lo que hacia es que dentro de la función eliminar le ponía la cadena de conexión y funcionaba pero eso al menos en mi opinión esta mal, ademas luego al mandar a llamar a cargardatos nuevamente me daba el mismo error, nunca he tenido ese problema, ya coloque la cadena en un modulo, en una clase y la mando a llamar desde ahí y tampoco funciona

    la verdad no se que es y he hecho el programa según las especificaciones del profesor por lo que por favor pediría su ayuda siempre basandose en el código que expongo a continuación, puse solo lo que considero tiene que ver con el problema

    Imports System.Configuration

    Imports System.Data

    Imports System.Data.SqlClient

    Public Class Form1

        Dimcmd AsSqlCommand

        Dimcadena AsString= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString

        Dimcnn AsNewSqlConnection(cadena)

       

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            cargardatos()

    End Sub


    Private Sub cargardatos()

            DataGridView1.Columns.Clear()

            Try

                cnn.Open()

                Dimsql AsNewSqlDataAdapter("select * from img", cnn)

                Dimda AsNewDataSet

                sql.Fill(da)

                DataGridView1.DataSource = da.Tables(0)

                Withcnn

                    If.State = ConnectionState.Open Then

                        .Close()

                    EndIf

                    .Dispose()

                EndWith

            Catchex AsException

                MsgBox(ex.Message.ToString)

            EndTry

        End Sub


    Private Sub eliminar(ByVal id As String)

            Try

                cnn.Open()

                Dimp AsNewSqlCommand("eliminar", cnn)

                p.CommandType = CommandType.StoredProcedure

                p.Parameters.Add("@codigo", SqlDbType.Int).Value = id

                p.ExecuteNonQuery()

                MessageBox.Show("registro eliminado satisfactoriamente")

                cargardatos()

                Withcnn

                    If.State = ConnectionState.Open Then

                        .Close()

                    EndIf

                    .Dispose()

                EndWith

            Catchex AsException

                MsgBox(ex.Message.ToString)

            End Try

        EndSub


    Por cierto también lo probé con la cadena de conexión siguiente:

    Dim cnn As New SqlConnection("Data Source=LINGONET\SQLEXPRESS;Initial Catalog=imagenes;Integrated Security=True")

    y con:

    Dim cnn As New SqlConnection("Data Source=.\SQLEXPRESS;Initial Catalog=imagenes;Integrated Security=True")

    y no me funciona.


    pabletoreto


    • Editado pabletoreto viernes, 9 de marzo de 2012 15:59
    viernes, 9 de marzo de 2012 15:45

Respuestas

  • "pabletoreto" escribió:

    > Mi problema es que uso una cadena de conexión con la cual no
    > tengo problemas al cargar por primeva vez los datos en el DGV,
    > pero al querer eliminar las filas seleccionas según un check
    > en la columna checkbox me aparece este error:
    >
    > the connectionstring property has not been initialized
    >
    > la verdad no se que es
    >
    > Dim cnn As New SqlConnection(cadena)
    >
    >    With cnn
    >      If.State = ConnectionState.Open Then
    >          .Close()
    >      End If
    >
    >      .Dispose()
    >
    >    End With

    Hola:

    No te preocupes de la cadena de conexión porque seguramente está bien definida. :-)

    ¿Sabes donde está el problema? En la llamada al método Dispose del objeto SqlConnection que efectúes en los métodos 'cargardatos' y 'eliminar'.

    Si estás trabajando con una variable objeto 'SqlConnection' a nivel del formulario

    Public Class Form1
    
       Dim cnn As New SqlConnection(cadena)
    
    End Class

    no llames a su método 'Dispose' porque lo que estás haciendo es DESTRUIR EL OBJETO, de ahí que cuando se ejecute de nuevo su método 'Open', obtengas la excepción No se ha inicializado la propiedad ConnectionString. Este mensaje de error se obtendrá en lo concerniente al tipo de dato SqlConnection. En otros objetos diferentes obtendrás otro mensaje de error, que al igual que el anterior, no nos proporciona suficiente información para averiguar lo que está mal.

    Si quieres trabajar con la misma variable objeto SqlConnection a nivel del formulario, tendrás que llamar a su método Dispose CUANDO SE CIERRE EL FORMULARIO, aunque yo te aconsejaría que no utilizaras variables objeto a nivel del formulario de algún tipo de dato que implemente la interfaz IDisponsable, como es el caso del objeto SqlConnection, porque entre otros problemas que te pueden surgir, ésta precisamente el que ahora nos ocupa: el querer utilizar un objeto que se ha destruido, aunque su valor no sea Nothing.

    Para llamar al método Dispose, tendrás que utilizar variables objetos de nivel local al procedimiento o método donde se declaran y se destruyen, y si no quieres llamar a dicho método de manera explícita, lo puedes hacer de manera implícita utilizando un bloque Using ... End Using.

       Using cnn As New SqlConnection(cadena)

          ' Acciones a ejecutar

       End Using

    Cuando se ejecute la línea 'End Using' el código se encargará de llamar automáticamente al método Dispose del objeto SqlConnection.

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.







    domingo, 11 de marzo de 2012 17:44
    Moderador
  • no estoy de acuerdo que estas lineas

    Dimcmd AsSqlCommand

    Dimcadena AsString= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString

    Dimcnn AsNewSqlConnection(cadena)

    las definas globales al formulario, no es correcto hacer eso

    Private Sub cargardatos()
    
    	Try
    
    		DataGridView1.Columns.Clear()
    
    		Dim cadena AsS tring= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString
    		Using cnn AsNewSqlConnection(cadena)
    
    			Dim sql As NewSqlDataAdapter("select * from img", cnn)
    			Dimd dt As New DataTable 
    			sql.Fill(dt)
    
    			DataGridView1.DataSource = dt
    
    		End Using
    
    	Catchex AsException
    		MsgBox(ex.Message.ToString)
    	EndTry
    
    End Sub

    y los mismo para el Eliminar(), la declaracion la haces cuando lo usas no global en el formulario

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

     entonces de ninguna manera es correcta dejarlas como global? lo pregunto porque entonces vaya profesor el que tengo, podrías orientarme en eso por favor

    pabletoreto

    • Marcado como respuesta pabletoreto domingo, 11 de marzo de 2012 19:07
    viernes, 9 de marzo de 2012 16:13

Todas las respuestas

  • no estoy de acuerdo que estas lineas

    Dimcmd AsSqlCommand

    Dimcadena AsString= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString

    Dimcnn AsNewSqlConnection(cadena)

    las definas globales al formulario, no es correcto hacer eso

    Private Sub cargardatos()
    
    	Try
    
    		DataGridView1.Columns.Clear()
    
    		Dim cadena AsS tring= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString
    		Using cnn AsNewSqlConnection(cadena)
    
    			Dim sql As NewSqlDataAdapter("select * from img", cnn)
    			Dimd dt As New DataTable 
    			sql.Fill(dt)
    
    			DataGridView1.DataSource = dt
    
    		End Using
    
    	Catchex AsException
    		MsgBox(ex.Message.ToString)
    	EndTry
    
    End Sub

    y los mismo para el Eliminar(), la declaracion la haces cuando lo usas no global en el formulario

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    viernes, 9 de marzo de 2012 16:06
  • no estoy de acuerdo que estas lineas

    Dimcmd AsSqlCommand

    Dimcadena AsString= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString

    Dimcnn AsNewSqlConnection(cadena)

    las definas globales al formulario, no es correcto hacer eso

    Private Sub cargardatos()
    
    	Try
    
    		DataGridView1.Columns.Clear()
    
    		Dim cadena AsS tring= ConfigurationManager.ConnectionStrings("cnn").ConnectionString.ToString
    		Using cnn AsNewSqlConnection(cadena)
    
    			Dim sql As NewSqlDataAdapter("select * from img", cnn)
    			Dimd dt As New DataTable 
    			sql.Fill(dt)
    
    			DataGridView1.DataSource = dt
    
    		End Using
    
    	Catchex AsException
    		MsgBox(ex.Message.ToString)
    	EndTry
    
    End Sub

    y los mismo para el Eliminar(), la declaracion la haces cuando lo usas no global en el formulario

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

     entonces de ninguna manera es correcta dejarlas como global? lo pregunto porque entonces vaya profesor el que tengo, podrías orientarme en eso por favor

    pabletoreto

    • Marcado como respuesta pabletoreto domingo, 11 de marzo de 2012 19:07
    viernes, 9 de marzo de 2012 16:13
  • Leandro,  quisiera saber porque es erróneo? me imagino que sera seguridad, porque si las define globlales las puede usar desde cualquier lugar, es como si las usara en un modulo, o crear una función o evento solo para abrir la conexion, después de abrir la conexion llama los otros dos eventos eliminar() y cargar_datos(), para ahorrar código.

    De verdad me dejaste duda yo creo una función para abrir la conexión y después la llamo desde mis eventos. Lo estoy haciendo mal?


    Cristian Carvajal Bahamon.

    viernes, 9 de marzo de 2012 17:58
  • entonces de ninguna manera es correcta dejarlas como global?

    definir una conexion global implica riesgos a que esta quede conectada por algun fallo en el codigo mal controlado

    por eso es recomedable ubicar la conexion dentro de un bloque using, con esto te aseguras la destruccion correcta de la conexion, es mas veras que ni siquiera use el close(), porque el bloque using lo hace por ti

    es mas ado.net mantiene un pool de conexion vigente, por lo que la destruccion tampoco es que se hace inmediata, ado.net la mantiene un tiempo por ti por eso si hace muchas operaciones seguirdad no es que se abre y cierra la conexion, sino que dejas que ado.net lo administre por ti

    yo no dejaria una conexion global, porque es para problemas

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    viernes, 9 de marzo de 2012 19:07
  • quisiera saber porque es erróneo? me imagino que sera seguridad

    un poco de seguridad, un poco de prolijidad en el codigo, otro de control de las conexiones ante un incorrecto cierre, otro poco de buenas practicas

    después de abrir la conexion llama los otros dos eventos eliminar() y cargar_datos(), para ahorrar código.

    a veces el ahorrar codigo termian siendo mas perjudicial definir un bloque que se repita en varios lugares

    ojo se podria hacer una libreriaque ayude

    recomendaria le des una vuelta a

    http://social.msdn.microsoft.com/Forums/es-ES/netfxes/thread/760f9f20-18c4-4abd-94f4-ba72e62bebf3

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    viernes, 9 de marzo de 2012 19:10
  • "pabletoreto" escribió:

    > Mi problema es que uso una cadena de conexión con la cual no
    > tengo problemas al cargar por primeva vez los datos en el DGV,
    > pero al querer eliminar las filas seleccionas según un check
    > en la columna checkbox me aparece este error:
    >
    > the connectionstring property has not been initialized
    >
    > la verdad no se que es
    >
    > Dim cnn As New SqlConnection(cadena)
    >
    >    With cnn
    >      If.State = ConnectionState.Open Then
    >          .Close()
    >      End If
    >
    >      .Dispose()
    >
    >    End With

    Hola:

    No te preocupes de la cadena de conexión porque seguramente está bien definida. :-)

    ¿Sabes donde está el problema? En la llamada al método Dispose del objeto SqlConnection que efectúes en los métodos 'cargardatos' y 'eliminar'.

    Si estás trabajando con una variable objeto 'SqlConnection' a nivel del formulario

    Public Class Form1
    
       Dim cnn As New SqlConnection(cadena)
    
    End Class

    no llames a su método 'Dispose' porque lo que estás haciendo es DESTRUIR EL OBJETO, de ahí que cuando se ejecute de nuevo su método 'Open', obtengas la excepción No se ha inicializado la propiedad ConnectionString. Este mensaje de error se obtendrá en lo concerniente al tipo de dato SqlConnection. En otros objetos diferentes obtendrás otro mensaje de error, que al igual que el anterior, no nos proporciona suficiente información para averiguar lo que está mal.

    Si quieres trabajar con la misma variable objeto SqlConnection a nivel del formulario, tendrás que llamar a su método Dispose CUANDO SE CIERRE EL FORMULARIO, aunque yo te aconsejaría que no utilizaras variables objeto a nivel del formulario de algún tipo de dato que implemente la interfaz IDisponsable, como es el caso del objeto SqlConnection, porque entre otros problemas que te pueden surgir, ésta precisamente el que ahora nos ocupa: el querer utilizar un objeto que se ha destruido, aunque su valor no sea Nothing.

    Para llamar al método Dispose, tendrás que utilizar variables objetos de nivel local al procedimiento o método donde se declaran y se destruyen, y si no quieres llamar a dicho método de manera explícita, lo puedes hacer de manera implícita utilizando un bloque Using ... End Using.

       Using cnn As New SqlConnection(cadena)

          ' Acciones a ejecutar

       End Using

    Cuando se ejecute la línea 'End Using' el código se encargará de llamar automáticamente al método Dispose del objeto SqlConnection.

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.







    domingo, 11 de marzo de 2012 17:44
    Moderador
  • "Crisltree" preguntó:

    > quisiera saber porque es erróneo?

    Hola, Cristian:

    Más que erróneo podríamos decir que no es conveniente o adecuado. Cuanto menor sea el ámbito de visibilidad de una variable, menor será el número de problemas que se te pueden presentar.

    Una variable declarada a nivel de una clase o un formulario, te dará menos problemas que una variable declarada como Public en un bloque Module ... End Module. Y una variable declarada como local en un procedimiento, pues muchísimos menos problemas que una variable declarada a nivel de clase o a nivel global.

    > porque si las define globlales las puede usar desde cualquier lugar

    Pues por eso mismo no se aconseja su utilización. Si bien es más fácil trabajar con variables globales, hay que tener mucha precaución y cuidado con los valores de dichas variables, y cuando nos surja un problema, nos sabremos en qué parte se ha producido.

    Si los usuarios dejaran de utilizar variables a nivel global, no habría tantas preguntas en éste o en cualquier otro foro de programación. Las variables globales son una "pesadilla" si no se sabe muy bien lo que se está haciendo, aparte que hay que tener un control permanente con ellas.

    > yo creo una función para abrir la conexión y después la llamo desde
    > mis eventos. Lo estoy haciendo mal?

    No es que lo estés haciendo mal, si no que no lo estás haciendo adecuadamente a como hoy en día marcan las normas de buenas prácticas.

    Si yo solamente necesito una conexión para conectarme y recuperar unos datos, ¿para qué quiero tener en memoria una variable del tipo Connection hasta que finalice la aplicación, o hasta que se cierre el formulario?

    Si por ejemplo necesitas un procedimiento para obtener un objeto DataTable, en el mismo procedimiento puedes declarar el objeto Connection:


        Public Function GetDataCustomers() As DataTable
    
            Try
                ' Configuramos una conexión con el origen de datos.
                '
                Using cnn As New SqlConnection(cadenaConexion)
    
                    ' Recuperamos todos los registros de la tabla Clientes
                    '
                    Dim sql As String = "SELECT * FROM Clientes"
    
                    Dim da As New SqlDataAdapter(sql, cnn)
    
                    ' Añadimos información sobre la clave principal de la tabla.
                    '
                    da.MissingSchemaAction = MissingSchemaAction.AddWithKey
    
                    Dim dt As New DataTable("Clientes")
    
                    da.Fill(dt)
    
                    Return dt
    
                End Using
    
            Catch ex As Exception
                Throw
    
            End Try
    
        End Function

    Como podrás observar, creamos, configuramos y destruimos los objetos que vamos a utilizar en el mismo procedimiento donde se van a utilizar, y al final obtenemos lo que realmente necesitamos, en éste caso, un objeto DataTable con todos los registros de nuestra tabla de Clientes.

    Lo que sí tendrías que tener a nivel global sería la cadena de conexión que va a utilizar todos los objetos Connection que se declaren, la cual se supone que siempre va a ser la misma, al menos si nuestra aplicación solamente se va a conectar con el mismo origen de datos.

    Cuando deseemos mostrar los datos en un control DataGridView, llamaríamos a la función de la siguiente manera:

            Try
                DataGridView1.DataSource = GetDataCustomers()
    
            Catch ex As Exception
                MessageBox.Show(ex.Message)
    
            End Try
    

    Para nada nos sirve tener a nivel global un objeto SqlConnection, ni tener una función para abrir y otra para cerrar la conexión.

    Tu hazme caso: cuanto menor sea el ámbito de visibilidad de una variable, más tiempo libre tendrás para dedicárselo a otros menesteres. :-)

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.

    domingo, 11 de marzo de 2012 18:28
    Moderador