I have a all day running data process running with .NET C#
I am getting the zombie error on trying to Rollback a transaction after a timeout occurs:
This SqlTransaction has completed; it is no longer usable.|System.InvalidOperationException: This SqlTransaction has completed; it is no longer usable.
at System.Data.SqlClient.SqlTransaction.ZombieCheck()
at System.Data.SqlClient.SqlTransaction.Rollback()
My code :
using (var transactionSql = connection.BeginTransaction())
{
using (var bulkCopy = new SqlBulkCopy(connection, SqlBulkCopyOptions.Default, transactionSql))
{
try
{
// Updating table1
var commandUpd1 = new SqlCommand(query, connection, transactionSql);
commandUpd1.ExecuteNonQuery();
// Inserting table2
var commandInsert1 = new SqlCommand(query2, connection, transactionSql);
commandInsert1.ExecuteNonQuery();
// My bulk on table3
bulkCopy.WriteToServer(dataTable);
// Updating table1
var commandUpd2 = new SqlCommand(query3, connection, transactionSql);
commandUpd2.ExecuteNonQuery();
// Inserting table2
var commandInsert3 = new SqlCommand(query4, connection, transactionSql);
commandInsert3.ExecuteNonQuery();
transactionSql.Commit(); // Timeout
}
catch (Exception ex)
{
transactionSql.Rollback(); //Zombie error
throw ex;
}
}
}
There is a side effect on the zombie error. Some sql I executed are committed. So I have a undesired state.
I know I could do something like that to avoid zombie exception : https://learn.microsoft.com/en-us/dotnet/api/system.data.sqlclient.sqltransaction?redirectedfrom=MSDN&view=netframework-4.8
But that will not fix that undesired persisted sql on database.
Why am I getting that error? How can I avoid that sql persisted on database ?
Update 1 As asked, my update and insert sql sent a date like that:
...
var date = DateTime.Now.ToString("s");
public static void UpdateMethod(long id, int status, string date, SqlConnection connection, SqlTransaction transactionSql)
{
date = date == null ? "NULL" : $"'{date}'";
var query = $"UPDATE table SET Status = {status}, Date = {date} WHERE Id = {id}";
var commandUpdate = new SqlCommand(query, connection, transactionSql);
commandUpdate.ExecuteNonQuery();
}
Thanks