Quelles sont les différences entre le modèle de transaction classique dans LINQ to SQL comme:
using(var context = Domain.Instance.GetContext())
{
try
{
context.Connection.Open();
context.Transaction = context.Connection.BeginTransaction();
/*code*/
context.Transaction.Commit();
}
catch
{
context.Transaction.Rollback();
}
}
par rapport à l'objet TransactionScope
using (var context = Domain.Instance.GetContext())
using (var scope = new TransactionScope())
{
try
{
/*code*/
scope.Complete();
}
catch
{
}
}
Linq2SQL utilisera une transaction implicite. Si toutes vos mises à jour sont effectuées dans un seul envoi, vous n'aurez peut-être pas besoin de gérer la transaction vous-même.
De la documentation (soulignement le mien):
Lorsque vous appelez SubmitChanges, LINQ to SQL vérifie si l'appel fait partie de la portée d'une transaction ou si la propriété de transaction (IDbTransaction) est définie sur une transaction locale démarrée par l'utilisateur. S'il ne trouve aucune transaction, LINQ to SQL démarre une transaction locale (IDbTransaction) et l'utilise pour exécuter les commandes SQL générées. Lorsque toutes les commandes SQL ont été exécutées avec succès, LINQ to SQL valide la transaction locale et résultats.
Il convient de noter que lors de l'utilisation de TransactionScope
il n'est pas nécessaire de try/catch
construire que vous avez. Il vous suffit d'appeler Complete
sur la portée afin de valider la transaction lorsque la portée est fermée.
Cela étant dit, TransactionScope
est généralement un meilleur choix car il vous permet d'imbriquer des appels à d'autres méthodes qui pourraient nécessiter une transaction sans que vous ayez à transmettre l'état de la transaction.
Lorsque vous appelez BeginTransaction
sur l'objet DbConnection
, vous devez passer cet objet de transaction si vous souhaitez effectuer d'autres opérations dans le même transaction, mais dans une méthode différente.
Avec TransactionScope
, tant que la portée existe, il gérera tout ce qui s'inscrit avec le courant Transaction
sur le thread, rendant votre code plus propre et plus maintenable.
En plus de cela, vous avez l'avantage supplémentaire de pouvoir utiliser d'autres ressources pouvant participer aux transactions, pas seulement la connexion à la base de données.
Il convient de noter que dans les situations où vous devez tirer le meilleur parti de vos connexions et opérations de base de données, vous ne voudrez peut-être pas utiliser TransactionScope
; même contre une base de données unique, vous exécutez la possibilité que le coordinateur de transactions distribuées soit utilisé et que la transaction soit transformée en transaction distribuée (même pour une connexion à une seule base de données).
Dans ces cas, tout en brouillant votre conception, vous pouvez envisager de passer une transaction spécifique à la connexion.
Ou , si vous savez que vous utiliserez une ressource de manière cohérente (et sur le même fil), vous voudrez peut-être créer une classe qui compte les références de votre connexion /transaction.
Vous créeriez une classe qui, lors de la construction, crée votre ressource/incrémente le nombre. Il implémenterait également IDisposable
(dans lequel vous décrémenteriez/relâcher/valider/abandonner lorsque le nombre est nul) et stocker le nombre dans une variable qui a ThreadStaticAttribute
lui est appliqué.
Cela vous permet de séparer la gestion des transactions du code logique et de conserver une ressource singulière assez efficacement (au lieu de passer à une transaction distribuée).
Une grande différence (leçon apprise à la dure) - TransactionScope utilise MS DTC pour la gestion des transactions.
Si votre application doit gérer uniquement les transactions de base de données et qu'aucun service ni appel distant n'est impliqué, vous pouvez ignorer les problèmes potentiels liés à MS DTC en utilisant une transaction native aux bases de données (DbTransactions).
TransactionScope fournit une gestion unifiée de tous les gestionnaires de ressources (serveur SQL, Active Directory, système de fichiers,…). De plus, on peut écrire son propre gestionnaire de ressources: du code qui détecte la portée de la transaction, le joint et fonctionne exactement comme le fait le serveur SQL: valide ou annule les modifications comme les autres participants à la transaction. Je croyais que TransactionScope était courant et j'ai oublié les transactions natives MS SQL jusqu'à ce qu'il échoue dans un énorme piège: Windows Server 2008 WEB Edition est livré avec un service de coordinateur de transactions distribuées restreint et l'étendue des transactions ne fonctionne que sur un seul ordinateur. Votre application ASP.NET échouera sur ce système si IIS et le serveur SQL sont installés sur des ordinateurs différents. Tenez compte du fait que la plupart des fournisseurs de domaine public fournissent l'édition Windows Server WEB et que le serveur SQL se trouve sur des serveurs distincts Cela signifie que vous devez travailler avec des transactions natives à l'aide d'une gestion explicite des transactions…
Je pense qu'ils sont fondamentalement les mêmes que la classe TransactionScope s'interface avec la connexion sous-jacente ADO.NET pour créer et valider ou annuler la transaction. Que la classe TransactionScope vient d'être créée pour rendre le travail avec le nettoyeur de persistance ADO.NET.
Edit: Clarifier ma déclaration en ce qui concerne ajout de casperOne c'est le TransactionScope qui créera la transaction et la connexion verra alors la transaction qui a été créée par le TransactionScope et l'utiliser car il est à sa disposition.