2009-10-23 4 views
5

In unserem aktuellen Projekt verwenden wir ADO.NET Entity Framework als Datenschicht für die Anwendung. Es gibt einige Aufgaben, die in einer Transaktion ausgeführt werden müssen, da in der Datenbank viel Arbeit erforderlich ist. Ich verwende eine TransactionScope, um diese Aufgaben zu umgeben.MSDTC Problem mit Transaktionen in ADO.NET Entity Framework

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

Das Problem ist, sobald ich ein TransactionScope bin mit einer Ausnahme auftritt:

System.Data.EntityException: Der zugrunde liegende Anbieter auf Öffnen fehlgeschlagen. ---> System.Transactions.TransactionManagerCommunicationException: Die Kommunikation mit dem zugrunde liegenden Transaktionsmanager ist fehlgeschlagen. ---> System.Runtime.InteropServices.COMException (0x80004005): Fehler HRESULT E_FAIL wurde von einem Aufruf an eine COM-Komponente zurückgegeben.

Es scheint, dass dieser Fehler etwas mit dem MSDTC (Microsoft Distributed Transaction Coordinator) zu tun hat. Wenn ich die Sicherheitskonfiguration von MSDTC ändere, wird eine weitere Ausnahme ausgelöst:

System.Data.EntityException: Der zugrunde liegende Provider ist bei Open fehlgeschlagen. ---> System.Transactions.TransactionManagerCommunicationException: Netzwerkzugriff für Distributed Transaction Manager (MSDTC) wurde deaktiviert. Aktivieren Sie DTC für den Netzwerkzugriff in der Sicherheitskonfiguration für MSDTC mit dem Verwaltungsprogramm für Komponentendienste.

MSDTC ist jedoch konfiguriert, die TransactionScope wird einen Fehler verursachen. Weiß jemand, was hier falsch läuft?

Antwort

-2

Hmm, scheint es zu funktionieren, wenn ich die TransactionScopeOption ändern zu "unterdrücken":

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

jeder macht, warum?

+4

Ich denke, Es verwendet in diesem Fall keine Transaktion, aber ich bin mir nicht sicher. –

+0

Ja, diese Option zeigt an, dass sie nicht an der Transaktion teilnehmen soll. –

+1

Ich bekomme den gleichen Fehler, aber es gibt keine Möglichkeit, das ist die beste Antwort. –

7

Standardmäßig ist der Netzwerkzugriff von MSDTC deaktiviert. Um es zu bekommen arbeiten, sollten Sie gehen zu

Systemsteuerung-> Administrative Tools-> Component Services-> Component Serivces-> Computes-> Arbeitsplatz-> Rechts Klick-> Einstellungen-> MSDTC-> Sicherheit Konfiguration

und überprüfen Sie folgende Kontrollkästchen DTC-Netzwerkzugriff, Eingehende zulassen, Outbound zulassen. Die Authentifizierung sollte entsprechend Ihrer Umgebung gewählt werden. Sie können auch das Tool DTCPing untersuchen, um verteilte Transaktionen zu debuggen. Um Ihnen eine Verknüpfung - Sie können ändern müssen Sie Registrierung:

HKLM \ Software \ Policies \ Microsoft \ Windows NT \ RPCRestrictRemoteClients = 0 HKLM \ Software \ Policies \ Microsoft \ Windows NT \ RPCEnableAuthEpResolution = 1

um alles in Betrieb zu nehmen.

+0

Danke, sagte DTCPing Werkzeug mir, dass es einige RPC-Endpunktfehler. Jetzt bin Überprüfung i out http://support.microsoft.com/kb/306843 & http://support.microsoft.com/kb/839880/EN-US/ vielleicht, dass die Lösung ist. – Alexander

+0

Für Windows 8 kann die „Sicherheitskonfiguration“ finden Sie hier: http://stackoverflow.com/questions/7694/how-do-i-enable-msdtc-on-sql-server/27263904#27263904 –

0

Dies bedeutet, dass es jede Transaktion unterdrückt, die aktuell beim Eingeben des Codeblocks wirksam ist. Daher werden alle Aktualisierungen Ihres Codes nicht rückgängig gemacht, wenn die äußere "Ambient" -Transaktion zu einem Rollback führt.

0

Dies ist der Artikel, den wir unser eigenes, ähnliches Problems bei der Lösung verwendet:

Troubleshooting Problems with MSDTC

Dies ist im Grunde eine Ergänzung zu Nikolay R's Antwort. Er hat bereits einige der in dem Artikel aufgeführten Vorschläge behandelt.

Hinweis: Der Artikel ist Teil der BizTalk-Dokumentation, aber es kann für alles, das MSDTC verwendet, gelten.

+0

Aktualisiert ähnliche Artikel http://msdn.microsoft.com/en-us/library/aa561924.aspx – JeremyWeir

3

Ja, es funktioniert mit Supress, weil Sie ihm sagen, die Ambient-Transaktion zu unterdrücken oder zu ignorieren und eine neue lokale Transaktion zu erstellen. Da es sich bei der Transaktion um eine lokale Transaktion handelt, handelt es sich nicht um eine verteilte Transaktion. Daher wird MSDTC nicht verwendet, aber Sie sollten Supress wahrscheinlich nicht verwenden und stattdessen Required verwenden.

0

"Wenn Sie Entity Framework mit Transaktionen verwenden, öffnet und schließt Entity Framework automatisch eine Verbindung mit jedem Datenbankaufruf. Wenn Sie also Transaktionen verwenden, versuchen Sie eine Transaktion über mehrere Verbindungen zu verteilen. Dies führt zu MSDTC."

Sie können Ihren Datenbankkontext in Ihrer Transaktion an die aufgerufene Klasse oder Funktion übergeben.

Vielleicht ist Ihre Antwort: MSSQL Error 'The underlying provider failed on Open'

0

Unterdrücken der Transaktion ist nützlich, wenn Sie einen Code ausführen möchten, die fehlschlagen könnten, aber Sie wollen nicht, die Transaktion abzubrechen, weil das fehlschlagen.

Die Frage, die Sie sich stellen müssen, ist die folgende: Zugriff auf mehr als 1 dauerhafte Ressource in Ihrem transactionScope? Ich meine, öffnest du Verbindungen zu mehr als einer DB?

Dies ist eine wichtige Frage, da die Transaktion in Richtung DTC eskaliert wird, wenn Sie auf mehr als 1 dauerhafte Ressource zugreifen.

Mindestens zwei dauerhafte Ressourcen, die einphasige Benachrichtigungen unterstützen, werden in die Transaktion aufgenommen. Wenn Sie beispielsweise eine einzelne Verbindung mit einer Verbindung herstellen, wird keine Transaktion gefördert. Wenn Sie jedoch eine zweite Verbindung zu einer Datenbank öffnen, durch die sich die Datenbank anmeldet, erkennt die System.Transactions-Infrastruktur, dass es sich um die zweite dauerhafte Ressource in der Transaktion handelt, und es an eine MSDTC-Transaktion eskaliert. Quelle:

//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(); 

}

Sie weitere Informationen über TransactionScopes finden, wie Verschachtelung Werke: MSDN

Wenn das der Fall ist, können Sie Ihr Problem durch Verschachtelung Ihre transactionscopes richtig, Beispiel lösen kann , ... unter MSDN.

Ich hoffe, diese Antwort kann Menschen in der Zukunft helfen.

0

Wenn der Distributed Transaction Coordinator-Dienst nicht gestartet wurde, kann Entity Framework keine Verbindung zur Datenbank herstellen. öffnen und starten Sie den Distributed Transaction Coordinator

Services -> Distributed Transaction Coordinator