Les transactions avec TransactionScope sont assez simples.
Créer une nouvelle TransactionScope (prefferable dans un bloc à l'aide)
Créer une nouvelle connexion Sql (si vous le faites dans l'autre sens, il ne fonctionnera pas)
Exécuter quelques opérations de CRUD
Remplissez le transaction
???
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 ;-)");
}
Rob ... pouvez-vous me laisser un commentaire sur ce sujet? –