Ok, un poco dramático, pero esta basado en una historia de la vida real. Hace un tiempo se me presentó el siguiente error
This SqlTransaction has completed; it is no longer usable. at System.Data.SqlClient.SqlTransaction.ZombieCheck() at System.Data.SqlClient.SqlTransaction.Rollback()
Un Zombie molestándome a estas alturas del partido y haciendo un Rollback
Resulta que esto se produce porque en algún punto de la transacción que estamos llevando a cabo; o finalizó satisfactoriamente o ya hicimos un rollbak (o sucedió algún otro fenómeno "inexplicable"). Posteriormente, y muy probablemente debido a un fallo en nuestra implementación (quizás en el manejo de errores), volvemos a invocar el rollback sobre la transacción que, como dijimos antes, por una u otra razón ya fue finalizada.
Nuestra implementación del Rollback probablemente fuese similar esto:
trn = con.BeginTransaction();
try
{
...
//Lógica de la transacción
...
trn.Commit();
}
catch(Exception ex)
{
...
//instrumentalización del error
...
trn.Rollback();
}
Si la transacción ya ha sido finalizada (por alguna situación en la lógica de la misma) e invocamos la linea trn.Rollback();, entonces se producirá el error en cuestión. Para paliar este tipo de posibles situaciones, la recomendación de Microsoft es simplemente ubicar un try/catch para la ejecución del rollback:
trn = con.BeginTransaction();
try
{
...
//Logica de la transaccion
...
trn.Commit()
}
catch(Exception ex)
{
...
//instrumentalización del error de la transacción
...
try
{
transaction.Rollback();
}
catch (Exception ex2)
{
...
//instrumentalización del error del Rollback
...
}
}
Como aprendí no es tan difícil lidiar con zombies... Al menos por el momento...Aquí un link con información adicional