2012-01-12 15 views
6

Recibo este mensaje de error cuando intento ejecutar el siguiente código.ExecuteNonQuery requiere que el comando tenga una transacción

ExecuteNonQuery requires the command to have a transaction when the connection assigned to the command is in a pending local transaction 

¿Alguien puede aconsejar dónde está el problema? Supongo que la raíz del problema es la parte donde trato de ejecutar un procedimiento almacenado.

el procedimiento almacenado se crea su propia transacción cuando se ejecute

using (SqlConnection conn = new SqlConnection(connStr)) 
      { 
       conn.Open(); 

       SqlCommand command = conn.CreateCommand(); 
       SqlTransaction transaction; 

       // Start a local transaction. 
       transaction = conn.BeginTransaction("createOrder"); 

       // Must assign both transaction object and connection 
       // to Command object for a pending local transaction 
       command.Connection = conn; 
       command.Transaction = transaction; 

       try 
       { 
        command.CommandText = "INSERT INTO rand_resupply_order (study_id, centre_id, date_created, created_by) " + 
         "VALUES (@study_id, @centre_id, @date_created, @created_by) SET @order_id = SCOPE_IDENTITY()"; 

        command.Parameters.Add("@study_id", SqlDbType.Int).Value = study_id; 
        command.Parameters.Add("@centre_id", SqlDbType.Int).Value = centre_id; 
        command.Parameters.Add("@date_created", SqlDbType.DateTime).Value = DateTime.Now; 
        command.Parameters.Add("@created_by", SqlDbType.VarChar).Value = username; 

        SqlParameter order_id = new SqlParameter("@order_id", SqlDbType.Int); 
        //study_name.Value = 
        order_id.Direction = ParameterDirection.Output; 
        command.Parameters.Add(order_id); 

        command.ExecuteNonQuery(); 
        command.Parameters.Clear(); 

        //loop resupply list 
        for (int i = 0; i < resupplyList.Count(); i++) 
        { 
         try 
         { 
          SqlCommand cmd = new SqlCommand("CreateOrder", conn); 
          cmd.CommandType = CommandType.StoredProcedure; 

          cmd.Parameters.Add("@study_id", SqlDbType.Int).Value = study_id; 
          cmd.Parameters.Add("@centre_id", SqlDbType.Int).Value = centre_id; 
          cmd.Parameters.Add("@created_by", SqlDbType.VarChar).Value = username; 
          cmd.Parameters.Add("@quantity", SqlDbType.VarChar).Value = resupplyList[i].Quantity; 
          cmd.Parameters.Add("@centre_id", SqlDbType.Int).Value = centre_id; 
          cmd.Parameters.Add("@depot_id", SqlDbType.VarChar).Value = depot_id; 
          cmd.Parameters.Add("@treatment_code", SqlDbType.Int).Value = centre_id; 
          cmd.Parameters.Add("@order_id", SqlDbType.Int).Value = (int)order_id.Value; 
          cmd.ExecuteNonQuery(); 
         } 
         catch (SqlException ex) 
         { 
          transaction.Rollback(); 
          ExceptionUtility.LogException(ex, "error"); 
          throw ex; 
         } 
         catch (Exception ex) 
         { 
          transaction.Rollback(); 
          ExceptionUtility.LogException(ex, "error"); 
          throw ex; 
         } 
         finally 
         { 
          conn.Close(); 
          conn.Dispose(); 
         } 

        } 

        return (int)order_id.Value; 

       } 
       catch (Exception ex) 
       { 
        transaction.Rollback(); 
        ExceptionUtility.LogException(ex, "error"); 
        throw ex; 
       } 
       finally 
       { 
        // Attempt to commit the transaction. 
        transaction.Commit(); 

        conn.Close(); 
        conn.Dispose(); 
        command.Dispose(); 
       } 
+0

Un pequeño punto - no se debe tratar de comprometerse en el 'finally' - que si, en cambio, estar en el' try', después de su operación –

+0

podría ser un poco viejo, pero puede usted por favor confirmar que mi respuesta resolvió tu problema? – Afshin

Respuesta

2

utilizando la transacción cadena de conexión no es popular por lo far.you puede eliminar cada cosas que se relacionan con SqlTransaction y luego envolver el código con TransactionScope

+1

Tenga mucho cuidado con TransactionScope. Parece bastante bueno cuando funciona. Pero he encontrado que es muy frágil al apuntar a servidores SQL no locales. Necesita que las cosas se configuren "exactamente". –

11

cuando usa transacciones, debe usarlas en todas partes.

cmd.Transaction = transaction; 
+0

¿Importa cuando los procedimientos almacenados en sí contienen su propia transacción? – pothios

+0

En realidad sí lo hace desde el punto de vista de .net. – Afshin

+0

así que la pregunta es cómo puedo lograr ejecutar una transacción que llamará a un procedimiento almacenado con su propia transacción :( – pothios

Cuestiones relacionadas