none
Error en transaction (a command is already in progress)

    Pregunta

  • Hola, estoy trabajando con transacciones usando una base de datos postgres, mi problema es que deseo usar datos de retorno en una consulta procesarla y enviarla en otra consulta...

    public void test()
            {
                bool retorno=false;
                string query;
                int t = 0;
                con = conexion.openConexion();
                using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required))
                {
                    try
                    {
                        using(NpgsqlCommand cmd= new NpgsqlCommand()) { 
                        query = "insert into ma(nombre,cantidad)values ('merenguete','525'); select max(id) from ma";
                        cmd.Connection = con;
                        cmd.CommandText = query;
                        leer = cmd.ExecuteReader();
                        while (leer.Read() == true)
                        {
                            if (leer.HasRows)
                            {
                                t = Convert.ToInt32(leer[0]);
    
                            }
                        }
    
                        }
                        using (NpgsqlCommand cmd = new NpgsqlCommand())
                        {
                            query = "insert into ma_det(nombre) values ('" + t.ToString() + "')";
                            comando.Connection = con;
                            comando.CommandText = query;
                            comando.ExecuteNonQuery();
                        }
    
                        MessageBox.Show("Buala " );
    
                    }
    
                    catch (Exception e)
                    {

    En este ejemplo logro retornar el id, pero no logro insertarlo en la otra tabla.. entiendo que el error es porque la conexion se quedo en la primera consulta...  me gustaria traer data procesarla y enviarla...

    jueves, 12 de julio de 2018 16:04

Respuestas

  • si hay un error en cualquier insert ninguna deberia realizarse.

    No se ve en el código que has puesto, debe estar un poco más abajo, pero sospecho que tienes mal ubicada la llamada al "tran.Complete()". Debería estar al final del bloque "try", para que si hay un error no se ejecute la llamada al "Complete". Pero si esa llamada la has puesto después del "catch", entonces se ejecuta siempre, haya o no haya error, por lo que la transacción siempre se confirma y no se deshacen los cambios aunque falle uno de los insert.
    • Marcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    jueves, 12 de julio de 2018 18:08
    Moderador
  • Asi es, estuve probando luego provocando errores, aun poniendo el tran.Complete().. Pero el error estaba en que la conexion se tiene que abrir dentro el ambiente del TransactionScope

    ...

    using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required))
                {
                    con = conexion.openConexion();
                    try
                    {
                        using(NpgsqlCommand cmd= new NpgsqlCommand()) { 
                        query = "insert into ma(nombre,cantidad)values ('ajaja','12588'); select max(id) from ma";
                        cmd.Connection = con;
                        cmd.CommandText = query;
                        leer = cmd.ExecuteReader();
                        while (leer.Read() == true)
                        {
                            
                                t = Convert.ToInt32(leer[0]);
    
                        }
                        leer.Close();
    
                        }
                        using (NpgsqlCommand cmd = new NpgsqlCommand())
                        {
                            query = "insert into ma_det(id) values (12)";
                            cmd.Connection = con;
                            cmd.CommandText = query;
                            cmd.ExecuteNonQuery();
                        }
    
                        MessageBox.Show("Buala " );
                        tran.Complete();
                    }

    • Marcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    jueves, 12 de julio de 2018 18:37

Todas las respuestas

  • El problema es que se to olvido cerrar el datareader de la primera consulta antes de ejecutar la segunda consulta. Mientras el datareader esta abierto, mantiene la conexion ocupada y no se puede usar para enviar ninguna otra cosa a la base de datos.

    Puedes poner leer.Close() o mejor todavia poner el "leer" dentro de un bloque "using". Al salir del using se llama internamente a Dispose, y Dispose llama a Close.

    Pero en tu caso hay otra solucion mejor todavia: Dado que usas el datareader para leer un unico velor de un unico registro, es preferible que lo sustituyas por ExecuteScalar (en lugar de ExecuteReader) y te evitas todos los problemas:

    t = Convert.ToInt32(cmd.ExecuteScalar());

    Por cierto, es completamente inutil poner "if leer.HasRows" dentro del while. Si leer no tuviese filas, nunca entraria en el while, por lo que nunca se ejecutaria el "if". Esto no tiene nada que ver con el error que te sale, y desaparecera si haces lo del ExecuteScalar. Solo lo advierto para que en el futuro puedas simplificar el codigo en los sitios en los que sea pertinente.

    jueves, 12 de julio de 2018 16:23
    Moderador
  • Que tal Alberto muchas gracias si efectivamente funciono.

    using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required))
                {
                    try
                    {
                        using(NpgsqlCommand cmd= new NpgsqlCommand()) { 
                        query = "insert into ma(nombre,cantidad)values ('test','125'); select max(id) from ma";
                        cmd.Connection = con;
                        cmd.CommandText = query;
                        leer = cmd.ExecuteReader();
                        while (leer.Read() == true)
                        {
                            
                                t = Convert.ToInt32(leer[0]);
    
                        }
                        leer.Close();
    
                        }
                        using (NpgsqlCommand cmd = new NpgsqlCommand())
                        {
                            query = "insert into ma_det(nombre) values ('" + t.ToString() + "')";
                            cmd.Connection = con;
                            cmd.CommandText = query;
                            cmd.ExecuteNonQuery();
                        }
    
                        MessageBox.Show("Buala " );
    
                    }
    

    probare tu otra sugerencia, pero aquí un detalle.. antes de poner el leer.Close(); los intentos fallido de hacer el insert en la segunda tabla, revisando me doy cuenta que si hizo el insert en la primera mas no en la segunda, esto no deberia ocurrir, si hay un error en cualquier insert ninguna deberia realizarse. Y ahora volviendo ha forzar el error ocurre lo mismo se da inserts en la primera tabla... :/

    • Marcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    • Desmarcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    jueves, 12 de julio de 2018 16:44
  • si hay un error en cualquier insert ninguna deberia realizarse.

    No se ve en el código que has puesto, debe estar un poco más abajo, pero sospecho que tienes mal ubicada la llamada al "tran.Complete()". Debería estar al final del bloque "try", para que si hay un error no se ejecute la llamada al "Complete". Pero si esa llamada la has puesto después del "catch", entonces se ejecuta siempre, haya o no haya error, por lo que la transacción siempre se confirma y no se deshacen los cambios aunque falle uno de los insert.
    • Marcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    jueves, 12 de julio de 2018 18:08
    Moderador
  • Asi es, estuve probando luego provocando errores, aun poniendo el tran.Complete().. Pero el error estaba en que la conexion se tiene que abrir dentro el ambiente del TransactionScope

    ...

    using (TransactionScope tran = new TransactionScope(TransactionScopeOption.Required))
                {
                    con = conexion.openConexion();
                    try
                    {
                        using(NpgsqlCommand cmd= new NpgsqlCommand()) { 
                        query = "insert into ma(nombre,cantidad)values ('ajaja','12588'); select max(id) from ma";
                        cmd.Connection = con;
                        cmd.CommandText = query;
                        leer = cmd.ExecuteReader();
                        while (leer.Read() == true)
                        {
                            
                                t = Convert.ToInt32(leer[0]);
    
                        }
                        leer.Close();
    
                        }
                        using (NpgsqlCommand cmd = new NpgsqlCommand())
                        {
                            query = "insert into ma_det(id) values (12)";
                            cmd.Connection = con;
                            cmd.CommandText = query;
                            cmd.ExecuteNonQuery();
                        }
    
                        MessageBox.Show("Buala " );
                        tran.Complete();
                    }

    • Marcado como respuesta Novatoj jueves, 12 de julio de 2018 18:38
    jueves, 12 de julio de 2018 18:37