Несколько SQLTRANDACTS в одном SQLConnection
-
01-10-2019 - |
Вопрос
У меня есть какой-код, который я хочу выполнить следующим образом. Но я продолжаю получать исключение «Это SQLTransaction завершило; это больше не используется» на 2 итерации. Может кто-нибудь помочь мне указать, что я здесь не так? Спасибо!
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();
}
Решение
Внутри петли вы либо совершаете, либо откат, но вы не сбрасываете ссылку на null
. SqlTransaction
В целом не используется как это, используется в using()
блок, как SqlConnection
является:
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);
}
}
Другие советы
Попробуйте установить ваш sqlTransaction
объект к нулю после утилизации. Сторона, вы действительно должны упасть те IDisposable
объекты в использовании блоков так Dispose
называется во все времена.
sqlTransaction.Commit();
sqlTransaction.Dispose();
sqlTransaction = null;
Вам нужно создать новый SqlTransaction
Объект на каждой итерации или полностью переместите транзакцию за пределами петли, если вы хотите, чтобы все операции внутри цикла произошли в одной транзакции. Как только вы совершаете транзакцию, необходимо снова позвонить за мочеиспускание на связи, чтобы начать новый. Вы не можете повторно использовать старый объект транзакции.