none
Problemas con SQLTransaction RRS feed

  • Pregunta

  • Hola, mi duda es la siguiente: Requiero hacer varios inserts dentro de una tabla en SQLServer. Tengo varias clases: Clase A Clase B Clase C Clase Funciones. Dentro de clase funciones genero los objetos A,B y C. Dependiendo varias condiciones, despues de crear A, se puede crear varios objetos B y uno o varios objetos C. Dentro de la clase A, B y C hay una clase que genera el query. Esta es la estructura:

    public insertar(SqlTransaction transaction){
     sql = "INSERT ...";
     try{
     SqlCommand _command = new SqlCommand();
     _command.Connection = transaction.Connection;
     _command.CommandType = CommandType.Text;
     _command.CommandText = sql;
     _command.Transaction = transaction;
     _command.ExecuteNonQuery();
     }catch (Exception ex){
     }
     }
    

    Dentro de la clase Funciones tengo el metodo que genera el Transaction:

    public SqlTransaction CreateTransaction(){
     try{
     SqlConnection _connection;
     _connection = new SqlConnection ("Data Source=...;Initial Catalog=...;User Id=...;Password=...");
     _connection.Open();
     SqlTransaction _transaction = _connection.BeginTransaction();
     return _transaction;
     }catch{
     throw;
     }
     }
    
    Y dentro de funciones tengo un try donde van la generacion de los objetos y la llamada a insertar(), y hasta al final tengo el commit.
    SqlTransaction _transaction = CreateTransaction();
    try{
     A();
     A.insertar(_transaction);
     B();
     B.insertar(_transaction);
     C();
     C.insertar(_transaction);
     _transaction.commit();
    }catch(){
     _transaction.Rollback();
    }
    

     

    El problema surge cuando al momento de insertar B me manda el siguiente error: System.InvalidOperationException: SqlTransaction se completo, ya no se puede utilizar.

    Si me pueden ayudar se los agradeceré mucho. Gracias. 

    miércoles, 30 de marzo de 2011 19:13

Respuestas

  • hola

    usa el TransactionScope

    mira como lo aplico aqui

    [N-Tier] – Desarrollo en capas - Ejemplo Facturacion - parte 3

    analzia cuando proceso la factura como se invocan variaos metodos y todos estan bajo la misma transaccion

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    miércoles, 30 de marzo de 2011 19:20
  • Hola Hiatomx, en .NET puedes manejar las transacciones en dos formas.

    La primera usando la Clase TransactionScope que lo que hace es definir un bloque de codigo transaccional y meidante el metodo complete haces el commit, ya no es necesario definir el rolback.

    Ahora ten en cuenta que para que puedas usar esa clase, debes iniciar el servicio de coordinador de transacciones distribuidas.

    Ten en cuenta tambien que al ser un servicio de Windows, puede llegar a demorar en tiempo de respuest haciendo que tu aplicacion sea un poco lenta.

    En el blog de Lendro como lo menciono arriba encontraras un ejemplo de un proceso de facturacion con la Clase TransactionScope.

    http://ltuttini.blogspot.com/2010/08/n-tier-desarrollo-en-capas-ejemplo.html

     

    Y en este arituclo encontras un proceso de facturacion con Transacciones pero con la clase SqlTransaction que es justamente lo que tu quieres.

    http://eperedo.comze.com/2009/10/maestro-detalle-con-sqltransaction/

     

    Ahi tiens las dos maneras de usar Transacciones en .NET y que mejor que con dos ejemplos de facturacion muy buenso y completos, tendras que analizar y tomar una desicion basada en tus necesidades.

    Espero haberte ayudado y que sea de utilidad.

     


    Programador .NET - Desarrollador 5 Estrellas.
    miércoles, 30 de marzo de 2011 20:19
  • Lo defini y todo pero al final me mando mensajes como...

    pero este mensaje es cuando usas el TransactionScope ?

    prueba de validar el DTC, como comenta aqui

    http://social.msdn.microsoft.com/forums/es-ES/vbes/thread/c82bcb8d-4f8f-48ce-be38-b423b8d32c64

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 31 de marzo de 2011 12:00

Todas las respuestas

  • hola

    usa el TransactionScope

    mira como lo aplico aqui

    [N-Tier] – Desarrollo en capas - Ejemplo Facturacion - parte 3

    analzia cuando proceso la factura como se invocan variaos metodos y todos estan bajo la misma transaccion

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    miércoles, 30 de marzo de 2011 19:20
  • Qque hacen el constructor de A, B, y los metodos insertar de A y B?
    Vicente Cartas Espinel - MVP XNA/DirectX

    Twitter - VicenteCartas

    Blog about C# and XNA Development

    Blog about Role Playing Games

    miércoles, 30 de marzo de 2011 19:31
  • Ok, estoy revisando tu código y me surge una duda, donde pongo mis try catch???
    miércoles, 30 de marzo de 2011 19:32
  • por fuera de la transaccion, abarcandola

     


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    miércoles, 30 de marzo de 2011 19:35
  • A B Y C generar los objetos, su contenido no es relevante. Entre cada creacion hay una serie de condiciones que me deciden si se crean uno o varios elementos B y C.

    La funciones insertar genera el sql y las intrucciones para insertar los objetos en una BD.

    public insertar(SqlTransaction transaction){
     sql = "INSERT INTO ...";
     try{
     SqlCommand _command = new SqlCommand();
     _command.Connection = transaction.Connection;
     _command.CommandType = CommandType.Text;
     _command.CommandText = sql;
     _command.Transaction = transaction;
     _command.ExecuteNonQuery();
     }catch (Exception ex){
     }
     }

    miércoles, 30 de marzo de 2011 19:35
  • Y usando el TransactionScope ya no es necesario usar un Rollback???
    miércoles, 30 de marzo de 2011 20:01
  • Hola Hiatomx, en .NET puedes manejar las transacciones en dos formas.

    La primera usando la Clase TransactionScope que lo que hace es definir un bloque de codigo transaccional y meidante el metodo complete haces el commit, ya no es necesario definir el rolback.

    Ahora ten en cuenta que para que puedas usar esa clase, debes iniciar el servicio de coordinador de transacciones distribuidas.

    Ten en cuenta tambien que al ser un servicio de Windows, puede llegar a demorar en tiempo de respuest haciendo que tu aplicacion sea un poco lenta.

    En el blog de Lendro como lo menciono arriba encontraras un ejemplo de un proceso de facturacion con la Clase TransactionScope.

    http://ltuttini.blogspot.com/2010/08/n-tier-desarrollo-en-capas-ejemplo.html

     

    Y en este arituclo encontras un proceso de facturacion con Transacciones pero con la clase SqlTransaction que es justamente lo que tu quieres.

    http://eperedo.comze.com/2009/10/maestro-detalle-con-sqltransaction/

     

    Ahi tiens las dos maneras de usar Transacciones en .NET y que mejor que con dos ejemplos de facturacion muy buenso y completos, tendras que analizar y tomar una desicion basada en tus necesidades.

    Espero haberte ayudado y que sea de utilidad.

     


    Programador .NET - Desarrollador 5 Estrellas.
    miércoles, 30 de marzo de 2011 20:19
  • A B Y C generar los objetos, su contenido no es relevante. Entre cada creacion hay una serie de condiciones que me deciden si se crean uno o varios elementos B y C.

    La funciones insertar genera el sql y las intrucciones para insertar los objetos en una BD.

     

    public insertar(SqlTransaction transaction){
     sql = "INSERT INTO ...";
     try{
     SqlCommand _command = new SqlCommand();
     _command.Connection = transaction.Connection;
     _command.CommandType = CommandType.Text;
     _command.CommandText = sql;
     _command.Transaction = transaction;
     _command.ExecuteNonQuery();
     }catch (Exception ex){
     }
     }

     

    La cosa es que entre tu CreateTransaction y la linea que da el error (B.insertar), hay algo que esta terminando la transaccion, cerrando la conexion, o en general haciendo algo raro. Solo puede ser el A(), A.insertar, o B(), no hay muchos otros sitios donde buscar :S

    Asi que en uno de esos tres sitios tiene que pasar algo (o yo estoy muy perdido, que tambien puede ser :p).

     


    Vicente Cartas Espinel - MVP XNA/DirectX

    Twitter - VicenteCartas

    Blog about C# and XNA Development

    Blog about Role Playing Games

    miércoles, 30 de marzo de 2011 20:56
  • exacto, solo defines el scope.Complete() para definir cuando se termina correctamente

    solo eso sino pasa por el Complete() la anula

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    miércoles, 30 de marzo de 2011 21:38
  • Efectivamente, al usar el metodo del TrasactionScope me empezo a tirar problemas con el DCT y todo eso.

    Hice unas cuantas modificaciones al codigo pero aun asi me manda el mismo mensaje.

    /*Metodo insertar en A B y C*/
    public void insertar(SqlTransaction transaction, SqlConnection conection)
        {
          string sql;
          string msg = "";
          sql = "INSERT ...";
          try{
            using (SqlCommand cmd = new SqlCommand(sql, conection, transaction)){
              cmd.ExecuteNonQuery();
            }
          }catch (Exception ex){
          }
        }
    
    /*Metodos en clase Funciones*/
     public SqlConnection CreateConection() {
          try{
            SqlConnection _connection;
            _connection = new SqlConnection("...");
            _connection.Open();
            return _connection;
          }catch{
            throw;
          }
        
        }
    
        public SqlTransaction CreateTransaction(SqlConnection _connection){
          try{
            SqlTransaction _transaction = _connection.BeginTransaction();
            return _transaction;
          }catch{
            throw;
          }
        }
    
    /*Cuerpo de metodo principal en funciones*/
    SqlConecction _conection = CreateConection();
    SqlTransaction _transaction = CreateTransaction();
    try{
     A();
     A.insertar(_transaction,_conection);
     B();
     B.insertar(_transaction,_conection);
     C();
     C.insertar(_transaction,_conection);
     _transaction.commit();
    }catch(){
     _transaction.Rollback();
    }
    

    miércoles, 30 de marzo de 2011 22:14
  • Lo defini y todo pero al final me mando mensajes como "Error de comunicación con el administrador de transacciones subyacente"

    Regrese entonces a usar SQLTransactions y se sigue mandando el error "SqlTransaction se completó; ya no se puede utilizar"

    Cuando lo debugeo, el objeto A se inserta correctamente, pero al momento de realizar el executeNonQuery en el objeto B, salta el error.

    Habra algun problema de que mi inserts estan en otras clases?

    Supongo que no debido a que le envio tanto un SQLConnection como un SQLTransaction, los cuales fueron definidos antes del try en donde creo e inserto los objetos.

    miércoles, 30 de marzo de 2011 22:29
  • Lo defini y todo pero al final me mando mensajes como...

    pero este mensaje es cuando usas el TransactionScope ?

    prueba de validar el DTC, como comenta aqui

    http://social.msdn.microsoft.com/forums/es-ES/vbes/thread/c82bcb8d-4f8f-48ce-be38-b423b8d32c64

     

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina
    jueves, 31 de marzo de 2011 12:00
  • Eso no me sirve
    martes, 4 de abril de 2017 18:11