2009-07-31 3 views
4

J'ai une situation où je cours dans un service WCF qui a TransactionScopeRequired = true, ce qui signifie qu'il y aura toujours une transaction ambiante.Existe-t-il un moyen de créer une connexion ADO.NET et d'ignorer la transaction ambiante?

Cependant, j'ai besoin de démarrer une nouvelle connexion qui sera là pour la durée de vie de l'application, ce qui signifie que je ne peux pas l'utiliser avec la transaction abbite.

Des idées sur comment faire cela? Il suffit de faire cela utilisera automatiquement la transaction ambiante:

Assert.IsNotNull(System.Transactions.Transaction.Current); 
var conn = new OracleConnection("my connection string"); 
conn.Open(); // <-- picks up ambient transaction, but I don't want that 

En fait, l'exemple pourrait être rendu plus simple en disant ceci:

OracleConnection conn; // <-- this is actually held around in another object that has a very long lifetime, well past the TransactionScope. 
using(var tx = new TransactionScope()) 
{ 
    conn = new OracleConnection("my connection string"); 
    conn.Open(); // <-- picks up ambient transaction, but I don't want that 
    // ... do stuff 
} 

Je ne veux pas que ma connexion pour prendre réellement TransactionScope. Dans le code actuel, il y a beaucoup plus de choses qui se font que les actions DB dans la portée, j'ai juste 1 que j'ai besoin de garder au-delà de la durée de vie de la portée de la transaction.


Je suppose que la situation réelle vaut la peine d'être mentionnée. Ce qui se passe réellement ici est que pendant un appel de service WCF, j'ajoute un objet à un cache en utilisant le bloc de mise en cache de la bibliothèque d'entreprise. Cet objet est une table de données, mais conserve également une connexion ouverte à Oracle sur laquelle la notification continue est configurée. Cela me permet d'actualiser automatiquement mon ensemble de données mis en cache lorsque les tables Oracle sous-jacentes changent.

L'élément de cache de données est accessible par n'importe quel nombre de threads initialisés WCF, qui s'exécutent tous dans leur propre étendue de transaction. Je suppose que vous pourriez penser à mettre un objet OracleConnection dans un cache. Un meilleur bloc de code text/exampe serait comme:

//beginning of a WCF service call 
using (var tx = new TransactionScope()) 
{ 
    var conn = new OracleConnection(); 
    var cmd = new OracleCommand(); 
    // set up OCN on the cmd and connection 
    var reader = cmd.ExecuteReader(); 
    cache.Add("conn", conn); 
    cache.Add("cmd", cmd); 
} 

//beginning of a second wcf service call 
using (var tx = new TransactionScope()) 
{ 
    var conn = cache.Get("conn"); 
    var cmd = cache.Get("cmd"); 
    var reader = cmd.ExecuteReader(); 
    // user reader to reload some data 
} 

Point étant, j'ai une connexion qui a une longue durée de vie sur plusieurs threads et les champs de transaction.

Répondre

5

Avez-vous essayé l'un des constructeurs de TransactionScope qui vous permet de définir la portée? La définition de la portée sur "Nécessite nouveau" crée une nouvelle transaction pour votre connexion dans Enlist. Définir la portée à "Supprimer" fait en sorte que votre connexion ne s'enrôle dans aucune transaction. Au moins, c'est comme ça que je lis la documentation. Je n'ai jamais eu ce besoin spécifique, moi-même.

using(var tx = new TransactionScope(TransactionScopeOption.RequiresNew)) 
{ 
    conn = new OracleConnection("my connection string"); 
    conn.Open(); 
} 
+0

D'une certaine manière, j'ai raté ce constructeur, merci! De manière intéressante, l'utilisation de .Suppress cause que mon application se bloque pour toujours en appelant OracleCommand.ExecuteReader(). Probablement parce que le bloc TransactionScope se termine bien avant l'appel d'ExecuteReader. (ajouté une note à mon OP) – CodingWithSpike

Questions connexes