Inicio › Foros › Lenguajes de programación, desarrollo, código fuente › .Net C# VB y PowerShell › System.ObjectDisposedException No se puede obtener acceso al objeto desechado
Etiquetado: .net, base de datos, bd, c sharp, c#, conexión, desechado, error, mysql, NetworkStream, ObjectDisposedException, programación, visual studio
- Este debate tiene 7 respuestas, 2 mensajes y ha sido actualizado por última vez el hace 5 años, 7 meses por Varios.
-
AutorEntradas
-
08/21/2019 a las 18:44 #3673VariosModerador
Hola, estoy desarrollando una aplicación en Visual Studio .Net C# con acceso a MySQL. Para el acceso uso los drivers nativos de MySQL para .Net.
Antes de añadir la referencia a la DLL de MySQL y de usar la conexión a MySQL la aplicación iba bien, pero desde que conecto con la base de datos para hacer select, insert y update, al principio me funciona, pero pasados unos minutos me sale este error:
System.ObjectDisposedException
HResult=0x80131622
Mensaje = No se puede obtener acceso al objeto desechado.
Nombre del objeto: ‘System.Net.Sockets.NetworkStream’.
Origen = System
Seguimiento de la pila:
en System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
en MySql.Data.MySqlClient.TimedStream.Read(Byte[] buffer, Int32 offset, Int32 count)
en MySql.Data.MySqlClient.MySqlStream.ReadFully(Stream stream, Byte[] buffer, Int32 offset, Int32 count)
en MySql.Data.MySqlClient.MySqlStream.LoadPacket()
en MySql.Data.MySqlClient.MySqlStream.ReadPacket()
en MySql.Data.MySqlClient.NativeDriver.FetchDataRow(Int32 statementId, Int32 columns)
en MySql.Data.MySqlClient.Driver.FetchDataRow(Int32 statementId, Int32 columns)
en MySql.Data.MySqlClient.Driver.SkipDataRow()
en MySql.Data.MySqlClient.ResultSet.Close()
en MySql.Data.MySqlClient.MySqlDataReader.NextResult()
en MySql.Data.MySqlClient.MySqlDataReader.Close()
en MySql.Data.MySqlClient.MySqlConnection.Close()
en MySql.Data.MySqlClient.MySqlConnection.Dispose(Boolean disposing)
en MySql.Data.MySqlClient.MySqlConnection.Finalize()Y la aplicación entera deja de funcionar.
¿A qué puede ser debido?
En principio capturo los errores en el código, por ejemplo:
C#12345678910111213141516171819202122232425262728293031public bool existeIDTelegram(int id){string sqlEjecutar = "Select id_telegram from cb_telegram where id_telegram = @id_telegram";try{conexionBD.Close();MySqlCommand runSQL = new MySqlCommand(sqlEjecutar, conexionBD);runSQL.Parameters.Add("@id_telegram", MySqlDbType.Int32).Value = id;conexionBD.Open();MySqlDataReader datosSQL = runSQL.ExecuteReader();//Si devuelve un registroif (datosSQL.Read()){return true;}else{return false;}}catch (MySqlException ex){new EscribirLog("Error al comprobar si existe ID usuario de Telegram en BD " + ex.Message, true);return false;}catch (ObjectDisposedException ex){new EscribirLog("Error al comprobar si existe ID usuario de Telegram en BD " + ex.Message, true);return false;}}Pero me sigue dando el error y la aplicación se cierra, no lo captura.
08/21/2019 a las 18:47 #3674alonsojpdSuperadministradorPásanos el código C# que usas para la conexión con la base de datos MySQL.
08/21/2019 a las 18:48 #3675VariosModeradorEste es el procedimiento que conecta con el servidor MySQL:
C#1234567891011121314151617181920212223242526272829public void conectarBD(){if (conexionBD != null)conexionBD.Close();string connStr =String.Format("server={0};port={1};user id={2}; password={3}; " +"database={4}; pooling=false;" +"Allow Zero Datetime=False;Convert Zero Datetime=True",this.servidor, this.puerto, this.usuario, this.contrasena, this.bd);try{conexionBD = new MySqlConnection(connStr);conexionBD.Open();new EscribirLog("Conectado a servidor BD " + this.servidor + " [" + this.bd + "]", true);//Conectamos a la BD (catálogo)//conexionBD.ChangeDatabase(this.bd);}catch (MySqlException ex){new EscribirLog("Error al conectar al servidor de BD " + this.servidor + " [" + this.bd + "] " + ex.Message, true);}catch (ObjectDisposedException ex){new EscribirLog("Error al conectar al servidor de BD " + this.servidor + "[" + this.bd + "] " + ex.Message, true);}}08/21/2019 a las 19:00 #3676alonsojpdSuperadministradorEl causante del problema puede ser el parámetro pooling=false de tu string de conexión. Cuando usas este parámetro a false estás indicando al motor de base de datos que cuando cierres la conexión con el servidor, en tu caso cuando haces:
conexionBD.Close();
Se cierra completamente, por lo que en la siguiente consulta has de volver a conectarte al servidor por completo y esto suele ser muy costoso. Si en todos tus procedimientos, como en el que nos has pasado de ejemplo, haces un:
conexionBD.Close();
y un
conexionBD.Open();
Por cada proceso de cada usuario que use tu aplicación y por cada procedimiento/función que internamente use la base de datos hará un close y un open, con el consiguiente consumo de recursos, pudiendo llegar a probar el error que nos comentas.
Puedes probar a cambiar el parámetro pooling a true, quedando tu código así:
C#1234567891011121314151617181920212223242526272829public void conectarBD(){if (conexionBD != null)conexionBD.Close();string connStr =String.Format("server={0};port={1};user id={2}; password={3}; " +"database={4}; pooling=true;" +"Allow Zero Datetime=False;Convert Zero Datetime=True",this.servidor, this.puerto, this.usuario, this.contrasena, this.bd);try{conexionBD = new MySqlConnection(connStr);conexionBD.Open();new EscribirLog("Conectado a servidor BD " + this.servidor + " [" + this.bd + "]", true);//Conectamos a la BD (catálogo)//conexionBD.ChangeDatabase(this.bd);}catch (MySqlException ex){new EscribirLog("Error al conectar al servidor de BD " + this.servidor + " [" + this.bd + "] " + ex.Message, true);}catch (ObjectDisposedException ex){new EscribirLog("Error al conectar al servidor de BD " + this.servidor + "[" + this.bd + "] " + ex.Message, true);}}Aunque deberías revisar el código para no hacer un close y open con cada consulta que ejecutas. Sería mucho más eficiente hacer un único open de la conexión durante una sesión.
08/21/2019 a las 19:06 #3677VariosModeradorHe puesto el pooling=true y ahora me va mucho mejor, me aguanta más tiempo y más conexiones. Por lo que seguramente es lo que dices, el close y open continuo. Que como al poner el pooling=true por lo que he leído indica al motor de base de datos que aunque se haga un close no se cierra la conexión realmente, y por eso me aguanta más.
Pero ahora me sale, cuando hay muchas conexiones, este error:
Timeout expired. The timeout period elapsed prior to obtaining a connection from the pool. This may have occurred because all pooled connections were in use and max pool size was reached.
08/21/2019 a las 19:34 #3678alonsojpdSuperadministradorEfectivamente el error se te estaba produciendo por el continuo close/open de la conexión con el servidor de MySQL.
Con pooling=true, como bien dices, se evita en cierta medida el problema, pero no del todo. El nuevo error que te aparece es porque superas el valor del parámetro max_pool_size.
Sin duda te recomiendo que revises el código y hagas una única conexión (open) al principio del programa y una desconexión al final (close).
08/21/2019 a las 20:15 #3680alonsojpdSuperadministradorPásanos algún ejemplo del código que uses para los updates y los insert de tu aplicación.
08/21/2019 a las 20:27 #3681VariosModeradorOs paso un ejemplo de update:
C#12345678910111213141516171819202122232425262728public bool validarUsuario(int id_telegram){string sqlEjecutar = "update cb_telegram set verificado = @si, fecha_verificacion = @fecha_verificacion " +"where id_telegram = @id_telegram";try{MySqlCommand comandoSQL = new MySqlCommand();conexionBD.Close();comandoSQL.Connection = conexionBD;comandoSQL.CommandText = sqlEjecutar;comandoSQL.Parameters.Add("@si", MySqlDbType.VarChar).Value = "S";comandoSQL.Parameters.Add("@id_telegram", MySqlDbType.Int32).Value = id_telegram;comandoSQL.Parameters.Add("@fecha_verificacion", MySqlDbType.Timestamp).Value = DateTime.Now;conexionBD.Open();comandoSQL.ExecuteNonQuery();return true;}catch (MySqlException ex){new EscribirLog("Error al validar/verificar usuario en BD: " + ex.Message, true);return false;}catch (ObjectDisposedException ex){new EscribirLog("Error al validar/verificar usuario en BD: " + ex.Message, true);return false;}}Otro de insert y update:
C#123456789101112131415161718192021222324252627282930313233343536373839public bool insertarPeso(int idUsuario, Single peso, string observacion){string sqlEjecutar;//Comprobamos si ya existe un peso en este día, para hacer un updateif (obtenerExistePesoFecha(idUsuario, DateTime.Now)){sqlEjecutar = "update cb_users_peso set peso = @peso, observacion = @observacion " +"where codigousuario = @codigousuario";}else //Si no existe hacemos un insert{sqlEjecutar = "insert into cb_users_peso (codigousuario, peso, fecha, observacion) " +"values (@codigousuario, @peso, @fecha, @observacion)";}try{MySqlCommand comandoSQL = new MySqlCommand();conexionBD.Close();comandoSQL.Connection = conexionBD;comandoSQL.CommandText = sqlEjecutar;comandoSQL.Parameters.Add("@codigousuario", MySqlDbType.Int32).Value = idUsuario;comandoSQL.Parameters.Add("@peso", MySqlDbType.Float).Value = peso;comandoSQL.Parameters.Add("@observacion", MySqlDbType.VarChar).Value = observacion;comandoSQL.Parameters.Add("@fecha", MySqlDbType.Timestamp).Value = DateTime.Now;conexionBD.Open();comandoSQL.ExecuteNonQuery();return true;}catch (MySqlException ex){new EscribirLog("Error al insertar registro de peso en tabla cb_users_peso en BD: " + ex.Message, true);return false;}catch (ObjectDisposedException ex){new EscribirLog("Error al validar/verificar usuario en BD: " + ex.Message, true);return false;}}Otro de select:
C#123456789101112131415161718192021222324252627282930public int obtenerPosicionCBRank(int idUsuario){string sqlEjecutar = "select ranking, ID from cb_users order by ranking desc";int posicion = 0;try{conexionBD.Close();MySqlCommand runSQL = new MySqlCommand(sqlEjecutar, conexionBD);conexionBD.Open();MySqlDataReader datosSQL = runSQL.ExecuteReader();//Recorremos los registros hasta llegar al que coincida con el ID del usuariowhile (datosSQL.Read()){posicion++;if (datosSQL["ID"].ToString()==Convert.ToString(idUsuario))break;}return posicion;}catch (MySqlException ex){new EscribirLog("Error obtener información la posición en el CBRank: " + ex.Message, true);return 0;}catch (ObjectDisposedException ex){new EscribirLog("Error al validar/verificar usuario en BD: " + ex.Message, true);return false;}} -
AutorEntradas
- Debes estar registrado para responder a este debate.