2009-05-23 7 views
4

Si un appel sql échoue, disons à timeout en raison d'un blocage, la transaction peut se transformer en une transaction zombie - Je suppose que mon code ou le code de l'infrastructure fait le rollback. Le SqlTransaction n'est pas nul, mais c'est un zombie qui peut lancer une erreur si vous essayez de faire un Rollback(). Je ne trouve pas la propriété .IsZombie.Existe-t-il un moyen de tester une transaction zombie potentielle pour voir si elle peut être annulée?

// Make sure the transaction is not null 
if (transaction != null) 
{ 
    //TODO: Is there a way to test a transaction to see if it can be rolled back? 
    transaction.Rollback(); 
} 

Répondre

2

Vous pouvez essayer d'utiliser la classe TransactionScope de l'espace de noms System.Transactions de .NET 2.0. Cette classe vous permet de spécifier un délai après lequel la transaction sera automatiquement annulée et annulée. ADO.NET dans 2.0+ .NET est TransactionScope conscient, et adhéreront automatiquement une DbTransaction dans le champ d'application si l'on est présent au moment où la base de données est appelée:

public void DoSomething() 
{ 
    using (TransactionScope scope = new TransactionScope(TransactionScopeOptions.Required, TimeSpan.FromSeconds(60))) 
    { 
     MyDac(); 

     scope.Complete(); // If timeout occurrs, this line is never hit, scope is disposed, which causes rollback if Complete() was not called 
    } 
} 

public class MyDac() 
{ 

    using (SqlConnection ...) 
    { 
     using (SqlCommand ...) 
     { 
      // Do something with ADO.NET here...it will autoenroll if a transaction scope is present 
     } 
    } 
} 

TransactionScope crée une System.Transactions.Transaction interne, qui autorise par défaut les transactions allégées vers SQL Server si un seul serveur est impliqué. Si plusieurs serveurs ou gestionnaires de ressources distribués sont impliqués dans la transaction, la transaction encapsulée par TransactionScope sera promue dans une transaction distribuée, ce qui nécessitera la coordination de MSDTC, ce qui peut compliquer l'utilisation de TransactionScope. Si toutes vos transactions sont allégées, TransactionScope peut offrir de nombreux avantages sur la gestion manuelle de vos transactions db.

0

Vous pouvez envisager de placer votre transaction dans le code de gestion de la base de données où vous pouvez tester @@ ERROR = 1205 pour déterminer si votre requête a été victime d'une impasse dans ce cas, vous pouvez réessayer ou ROLLBACK. Autoriser les applications client à créer et gérer des transactions est un peu risqué et préférable à éviter si possible.

Hope this helps,

Bill

+0

J'aimerais pouvoir passer facilement aux transactions côté serveur. J'ai 500 procédures stockées jumelées avec une couche d'accès aux données ADO.NET générée par code. La plupart des invocations transactionnelles ont été ajoutées comme standard. – MatthewMartin

1

Je vous demande pardon mais je ne peux pas éviter d'être en désaccord. Les transactions client sont ce qui permet d'avoir une opération atomique de processus métier. Si vous voulez déplacer toutes les opérations transactionnelles dans DB, vous y introduisez invariablement une logique métier. C'est une approche, mais fortement non recommandée à condition que vous utilisiez une logique légèrement complexe sur votre programme. Avoir whiles/for/foreachs, les contrôles de chaînes et d'autres opérations triviales sont vraiment lourds à déplacer dans DB (et parfois, même impossible). L'indice de blocage, cependant, semble être très utile et fournit un contrôle supplémentaire à l'application client (qui est le meilleur moyen d'y aller, à mon avis).

Salutations

+2

Bienvenue à la pile sur le flux, le point intéressant et la plupart du temps d'accord. Je ne suis pas sûr à qui vous répondez, la convention sur SO est cette "réponse" -y les choses vont dans les réponses et "discussion" -y choses vont dans les commentaires avec @ nom pour clarifier le destinataire. – MatthewMartin

Questions connexes