Question

Dans notre projet actuel, nous utilisons ADO.NET Entity Framework en tant que couche de données pour l'application. Certaines tâches doivent être exécutées dans une transaction car la base de données demande beaucoup de travail. J'utilise un TransactionScope pour entourer ces tâches.

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
    // Do something...
    transactionScope.Complete();
}

Le problème, c'est que dès que j'utilise un TransactionScope une exception se produit:

  

System.Data.EntityException: le fournisseur sous-jacent a échoué lors de l'ouverture. --- > System.Transactions.TransactionManagerCommunicationException: la communication avec le gestionnaire de transactions sous-jacent a échoué. --- > System.Runtime.InteropServices.COMException (0x80004005): L'erreur HRESULT E_FAIL a été renvoyée à partir d'un appel à un composant COM.

Il semble que cette erreur doive faire quelque chose avec le MSDTC (Coordinateur de transactions distribuées Microsoft). Lorsque je modifie la configuration de sécurité de MSDTC, une autre exception est levée:

  

System.Data.EntityException: le fournisseur sous-jacent a échoué lors de l'ouverture. --- > System.Transactions.TransactionManagerCommunicationException: l'accès réseau pour MSDTC (Distributed Transaction Manager) a été désactivé. Veuillez activer DTC pour l'accès réseau dans la configuration de sécurité pour MSDTC à l'aide de l'outil d'administration de Component Services.

Quelle que soit la configuration de MSDTC, le TransactionScope provoquera une erreur. Est-ce que quelqu'un sait ce qui ne va pas ici?

Était-ce utile?

La solution 8

Hmm, cela semble fonctionner lorsque je change de TransactionScopeOption pour "Supprimer":

using (TransactionScope transactionScope = new TransactionScope(TransactionScopeOption.Suppress))
{
    ...
}

Est-ce que tout le monde sait pourquoi?

Autres conseils

Par défaut, MSDTC a désactivé l'accès au réseau. Pour que cela fonctionne, vous devez aller à

  

Panneau de configuration - > Administratif   Outils- > Component Services- > Component   Services - > Calculs - > Mon ordinateur- > Droite   Cliquez sur > Propriétés sur > MSDTC- > Sécurité   Configuration

et cochez les cases suivantes Accès DTC réseau, Autoriser entrants, Autoriser sortants. L’authentification doit être choisie en fonction de votre environnement. Vous pouvez également consulter DTCPing pour déboguer les transactions distribuées. Pour vous donner un raccourci, vous devrez peut-être modifier votre registre:

  

HKLM \ Software \ Policies \ Microsoft \ Windows   NT \ RPCRestrictRemoteClients = 0   HKLM \ Logiciel \ Stratégies \ Microsoft \ Windows NT \ RPCEnableAuthEpResolution = 1

pour que tout soit opérationnel.

Oui, cela fonctionne avec Supress, car vous lui dites de supprimer ou d’ignorer la transaction ambiante et de créer une nouvelle transaction locale. Étant donné que la transaction est locale, il ne s’agit pas d’une transaction distribuée, elle n’utilise donc pas MSDTC, mais vous ne devriez probablement pas utiliser Suppress et utilisez plutôt Required.

Cela signifie qu’elle supprime toute transaction susceptible d’être effective lors de la saisie de votre bloc de code. Par conséquent, les mises à jour effectuées par votre code ne seront pas restaurées si le message "ambiant" extérieur est mis à jour. la transaction décide de revenir en arrière.

Ceci est l'article que nous avons utilisé pour résoudre notre propre problème similaire:

Résolution des problèmes liés à MSDTC

Il s’agit en réalité d’un additif à la réponse Nikolay R . Il a déjà couvert certaines des suggestions énumérées dans l'article.

Remarque: cet article fait partie de la documentation de Biztalk, mais il peut s'appliquer à tout ce qui utilise MSDTC.

" Si vous utilisez Entity Framework avec Transactions, Entity Framework ouvre et ferme automatiquement une connexion avec chaque appel de base de données. Ainsi, lorsque vous utilisez des transactions, vous essayez de répartir une transaction sur plusieurs connexions. Cela passe au MSDTC. "

Vous pouvez transmettre le contexte de votre base de données à la classe ou à la fonction appelée de votre transaction.

C'est peut-être votre réponse: Erreur MSSQL 'Le fournisseur sous-jacent a échoué à l'ouverture'

Il est utile de supprimer la transaction si vous souhaitez exécuter du code susceptible d’échouer mais de ne pas abandonner la transaction à cause de cet échec.

La question que vous devez vous poser est la suivante: Accédez-vous à plus d'une ressource durable dans votre transactionScope? Je veux dire, ouvrez-vous des connexions à plus de 1 DB?

Il s'agit d'une question importante, car la transaction sera transmise vers DTC si vous accédez à plus d'une ressource durable.

Au moins deux ressources durables prenant en charge les notifications en une phase sont inscrites dans la transaction. Par exemple, l’inscription d’une connexion unique avec ne provoque pas la promotion d’une transaction. Cependant, chaque fois que vous ouvrez une deuxième connexion à une base de données entraînant l'inscription de la base de données, l'infrastructure System.Transactions détecte qu'il s'agit de la deuxième ressource durable de la transaction et l'intègre à une transaction MSDTC. Source: MSDN

Si tel est le cas, vous pouvez résoudre votre problème en imbriquant correctement vos transactionscopes. Exemple:

//Create rootScope
using(TransactionScope rootScope = new TransactionScope()) 
{ 
    using(TransactionScope scope2 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB1
         ...

         //Complete this ambient transaction
         scope2.Complete();
    } 

    using(TransactionScope scope3 = new 
    TransactionScope(TransactionScopeOption.Required)) 
    {
         //Do work on DB2
         ...

         //Complete this ambient transaction
         scope3.Complete();
    } 

    //Complete rootScope
    //The whole transaction will only be committed if you call 
    //Complete on the rootScope
    rootScope.Complete();

}

Vous pouvez trouver plus d'informations sur TransactionScopes, le fonctionnement de l'imbrication, ... sur MSDN .

J'espère que cette réponse pourra aider les gens à l'avenir.

Si le service Distributed Transaction Coordinator n'est pas démarré, Entity Framework ne peut pas se connecter à la base de données. Ouvrez et démarrez le coordinateur de transaction distribuée

Services - > Coordinateur de transaction distribuée

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top