Pregunta

Tengo un código que quiero para ejecutar la siguiente manera. Pero me siguen dando la excepción "Este SqlTransaction ha completado, y ya no es utilizable" en la segunda iteración. Es posible que alguien me ayude señalar lo que estoy haciendo mal aquí? Gracias!

    SqlConnection cn = (SqlConnection)SqlConnectionManager.Instance.GetUserConnection(user);
 cn.Open();
 try
 {
    foreach (Master mRecord in masterList)
  {
   if (sqlTransaction == null)
       sqlTransaction = cn.BeginTransaction();
   SqlCommand cm = cn.CreateCommand();
   cm.Transaction = sqlTransaction;
   cm.CommandType = CommandType.StoredProcedure;
   cm.CommandText = "pr_InsertRecords";
       try
   {
    cm.ExecuteNonQuery();
    Debug.WriteLine("Auditor.Write: end sql table value param");
    sqlTransaction.Commit();
    sqlTransaction.Dispose();
   }
   catch (Exception Ex)
   {
    Debug.WriteLine(" Exception message: " + Ex.Message);
    if (Ex.InnerException != null)
    {
     Debug.WriteLine("Inner exception message" + Ex.InnerException.Message);
    }
    sqlTransaction.Rollback();
   }
  }
 }
 finally
 {
        cn.Close();
      }
¿Fue útil?

Solución

Dentro del bucle se confirma o retrotrae, pero no restablece la referencia a null. SqlTransaction en general no se utiliza como este, se utiliza en un bloque using(), tal como un SqlConnection es:

using (SqlConnection cn = SqlConnectionManager.Instance.GetUserConnection(user)) 
{
  foreach (Master mRecord in masterList)
  {
  try
  {
    using (SqlTransaction sqlTransaction = cn.BeginTransaction()) 
    {
      using (SqlCommand cm = cn.CreateCommand()) 
      {
        cm.Transaction = sqlTransaction;
        cm.CommandType = CommandType.StoredProcedure;
        cm.CommandText = "pr_InsertRecords";
        cm.ExecuteNonQuery();
      }
      sqlTransaction.Commit();
      Debug.WriteLine("Auditor.Write: end sql table value param");
    }
  }
  catch (Exception Ex)
  {
    Debug.WriteLine(" Exception message: " + Ex.Message);
  }
}

Otros consejos

Trate de establecer el objeto de sqlTransaction nula después de desechar la misma. Nota al margen, que realmente debería estar envolviendo esos objetos IDisposable en el uso de los bloques para Dispose se llama en todo momento.

sqlTransaction.Commit();
sqlTransaction.Dispose();
sqlTransaction = null;

Se necesita crear un nuevo objeto SqlTransaction en cada iteración o mover la transacción por completo fuera del bucle si quieren todas las operaciones dentro del bucle que se produzca en una sola transacción. Una vez que se compromete una transacción, es necesario llamar BeginTransaction de nuevo en la conexión para comenzar una nueva. No se puede volver a utilizar el objeto de transacción de edad.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top