2010-10-21 4 views
1

Où puis-je trouver des informations ou comment puis-je gérer les transactions SQL Server dans un thread BackgroundWorker? Je comprends que la gestion des erreurs ne doit pas être définie dans l'événement "DoWork" et que l'erreur est gérée en interne et transmise à "RunWorkerCompleted".NET BackgroundWorker et SQLTransactions

J'utilise actuellement SubSonic comme DAL et je passe de longs insertions et mises à jour Le problème que j'ai est que quand quelque chose échoue, rien n'est rollback, je décidais d'utiliser un transactioncope mais je ne trouvais pas d'informations sur l'utilisation des transactions avec un thread BackgroundWorker

+0

Rob ... pouvez-vous me laisser un commentaire sur ce sujet? –

Répondre

1

Les transactions avec TransactionScope sont assez simples.

  1. Créer une nouvelle TransactionScope (prefferable dans un bloc à l'aide)

  2. Créer une nouvelle connexion Sql (si vous le faites dans l'autre sens, il ne fonctionnera pas)

  3. Exécuter quelques opérations de CRUD

  4. Remplissez le transaction

  5. ???

  6. PROFIT !!!

Aux termes de subsonique c'est ce que vous avez à faire:

using (var ts = new TransactionScope()) 
using (new SubSonic.SharedDbConnectionScope()) 
{ 

    DoSomethingWithYourData(); 

    ts.Complete(); 
} 

C'est ce qui se passe en arrière-plan:

Si vous créez une nouvelle TransactionScope, l'opération de propriété statique. Le courant est défini sur votre transaction. Maintenant, si vous créez un nouveau DbConnection, les connexions lui-même regarde si Transaction.Current n'est pas null et s'abonne à l'événement TransactionCompleted.

Si vous appelez ts.Complete() avant que la connexion soit supprimée, la transaction est validée, sinon elle sera annulée et une exception est lancée dans la méthode TransactionScopes Dispose(). SubSonic lui-même va créer une nouvelle connexion pour chaque instruction que vous exécutez (pas de bug, c'est par desing) mais pas pratique pour les transactions. C'est la raison pour laquelle SharedDbConnectionScope() existe. Il fonctionne de la même façon que TransactionScope (si un nouveau AutomaticConnectionScope détecte qu'il existe un SharedDbConnectionScope() en cours, sa connexion sera utilisée, sinon une nouvelle connexion sera créée

Par ailleurs, la syntaxe using n'est rien d'autre :

var obj = new ObjectThatImplementsIDisposable(); 
try 
{ 

} 
finally 
{ 
    obj.Dispose(); 
} 

longue histoire courte: il ne touche pas votre transaction si vous exécutez dans un thread ou BackgroundWorker Cependant, vous devez garder à l'esprit que, si vous utilisez un SharedDbConnecionScope() même les requêtes d'autres threads. utilisez-les et je ne pense pas que la librairie SqlClient soit sûre pour les threads (mais je peux me tromper, mais MySqlClient ne l'est certainement pas.

Conculstion: Je passe à TransactionScope car il est facile à utiliser, flexible, générique (et si vous décidez un jour passer à MySQL ou Oracle avec votre application, vous n'avez pas à vous)

En lisant votre première partie de la question: - Je pense qu'il est mauvais de laisser la méthode DoWork de BackGroundWorker lancer une exception. Mais vous pouvez utiliser cette approche:

private void worker_DoWork(object sender, DoWorkEventArgs e) 
{ 
    try 
    { 
     ExecuteATransaction() 
    } 
    catch (Exception ex) 
    { 
     RollBackTransaction(); 
     e.Result = ex; 
    } 
} 

private void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
{ 
    if (e.Result && e.Result.GetType() == typeof(Exception)) 
     throw ((Exception)e.Result); 
    else 
     Console.WriteLine("Everything went better than expected ;-)"); 
} 
+0

Merci d'avoir répondu. J'ai lu quelque part (en cherchant l'intel) qu'il n'est pas recommandé d'avoir un bloc TRY CATCH dans le DoWork() d'un thread BackgroundWorker. –

+1

Ok, une recherche google rapide vérifié que: http://social.msdn.microsoft.com/forums/en-US/Vsexpressvcs/thread/74d91404-9bc8-4f8f-8eab-4265afbcb101/ la ligne de fond est. Ne gérez pas les exceptions, mais évaluez la propriété e.Error dans l'événement RunWorkerCompleted. Quoi qu'il en soit, cela ne signifie pas que vous ne pouvez pas avoir d'exceptions dans l'événement DoWork() et qu'avec TransactionScope, vous n'avez pas besoin d'intercepter les exceptions pour annuler la transaction, alors ça devrait aller. –