2010-08-24 30 views
2

J'ai du code que je veux exécuter comme suit. Mais je reçois toujours l'exception "Cette SqlTransaction est terminée, elle n'est plus utilisable" à la 2ème itération. Quelqu'un pourrait-il m'aider à souligner ce que je fais mal ici? Merci!sqltransactions multiples dans single sqlconnection

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(); 
     } 

Répondre

4

intérieur de la boucle vous soit validée ou annulée, mais vous ne remettez pas la référence à null. SqlTransaction en général n'est pas utilisé comme cela, est utilisé dans un bloc using(), tout comme SqlConnection est:

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); 
    } 
} 
+0

Salut Remus, une question au sujet de cette approche. Que faire si le SqlTransaction est passé à la méthode en tant que paramètre? par exemple: public void Ecrire (SqlTransaction SqlTransaction, Liste masterRecords, utilisateur de l'utilisateur, la méthode InsertMethod) { } – EndlessSpace

+1

Dans ce cas, l'appelant doit aussi passer le SqlConnection à utiliser, et est la responsabilité de l'appelant d'avoir un ' using' le bloc. Votre méthode, en tant qu'appelant, ne doit pas commettre ni disposer l'objet SqlTransaction transmis, car si tel est le cas, cela le rendrait inutilisable par l'appelant. –

2

Vous devez créer un nouvel objet SqlTransaction à chaque itération ou déplacer la transaction complètement en dehors de la boucle si vous êtes désireux de toutes les opérations à l'intérieur de la boucle de se produire en une seule transaction. Une fois que vous avez validé une transaction, il est nécessaire d'appeler à nouveau BeginTransaction sur la connexion pour en démarrer une nouvelle. Vous ne pouvez pas réutiliser l'ancien objet de transaction.

2

Essayez de définir votre objet sqlTransaction sur null après l'avoir jeté. Side note, vous devriez vraiment être envelopper ces objets IDisposable en utilisant des blocs de sorte que Dispose est appelé à tout moment.

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