2010-03-23 15 views
12

Ich habe eine Routine, die eine rekursive Schleife verwendet, um Elemente in eine SQL Server 2005-Datenbank einzufügen Der erste Aufruf, der die Schleife initiiert, ist in einer Transaktion mit TransactionScope eingeschlossen. Beim ersten Aufruf von ProcessItem werden die myItem-Daten wie erwartet in die Datenbank eingefügt. Wenn jedoch ProcessItem von ProcessItemLinks oder ProcessItemComments aufgerufen wird, erhalte ich den folgenden Fehler.Warum ist der TransactionScope-Vorgang nicht gültig?

„Die Operation ist für den Zustand der Transaktion ungültig“

ich dies mit VS 2008 auf Windows 7 im Debug leite und haben laufen die MSDTC verteilte Transaktionen zu ermöglichen. Der folgende Code ist nicht mein Produktionscode, sondern ist genau gleich. Die AddItemToDatabase ist eine Methode für eine Klasse, die ich nicht ändern kann, und verwendet einen Standard ExecuteNonQuery(), der eine Verbindung erstellt, die dann geschlossen und nach Abschluss beendet wird.

Ich habe andere Postings hier und im Internet angeschaut und kann dieses Problem immer noch nicht lösen. Jede Hilfe würde sehr geschätzt werden.

using (TransactionScope processItem = new TransactionScope()) 
{ 
    foreach (Item myItem in itemsList) 
    { 
     ProcessItem(myItem); 
    } 
    processItem.Complete(); 
}  
private void ProcessItem(Item myItem) 
{ 
    AddItemToDatabase(myItem); 
    ProcessItemLinks(myItem); 
    ProcessItemComments(myItem); 
}  
private void ProcessItemLinks(Item myItem) 
{ 
    foreach (Item link in myItem.Links) 
    { 
     ProcessItem(link); 
    } 
} 
private void ProcessItemComments(Item myItem) 
{ 
    foreach (Item comment in myItem.Comments) 
    { 
     ProcessItem(comment); 
    } 
} 

Hier ist der obere Teil des Stack-Trace. Leider kann ich den Aufbau bis zu diesem Zeitpunkt nicht als sensible Unternehmensinformationen darstellen, die ich nicht offen legen kann.

at System.Transactions.TransactionState.EnlistPromotableSinglePhase(InternalTransaction tx, IPromotableSinglePhaseNotification promotableSinglePhaseNotification, Transaction atomicTransaction) 
    at System.Transactions.Transaction.EnlistPromotableSinglePhase(IPromotableSinglePhaseNotification promotableSinglePhaseNotification) 
    at System.Data.SqlClient.SqlInternalConnection.EnlistNonNull(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnection.Enlist(Transaction tx) 
    at System.Data.SqlClient.SqlInternalConnectionTds.Activate(Transaction transaction) 
    at System.Data.ProviderBase.DbConnectionInternal.ActivateConnection(Transaction transaction) 
    at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject) 
    at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection) 
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory) 
    at System.Data.SqlClient.SqlConnection.Open() 
+0

Könnten Sie den Stack-Trace schreiben der Ausnahme? –

+0

Ich habe so viel von der Spur hinzugefügt wie erlaubt. Hoffe es ist genug! – Cragly

+0

Können Sie die gesamte Ausnahme posten? Veröffentlichen Sie die Ausgabe von ex.ToString() und redigieren Sie etwas Sensitives. Ich frage mich, ob es eine InnerException oder zwei gibt. –

Antwort

23

verteilte Transaktionen meine Haare gehen grau vorzeitig :)

üblichen Verdächtigen

  1. Firewall blockiert MSDTC
  2. Ihre Transaktion aus irgendeinem Grund eine Zeitüberschreitung (versuchen Sie das Timeout zu erhöhen)
  3. Sie haben einen anderen Transaktionsbereich irgendwo oben auf dem Code, der mit der aktuellen Transaktion
  4. unordentlich ist

Testen Sie, ob MSDTC funktioniert gut mit Tools wie DTCPing

Auch Test durch eine kleine Anzahl von Elementen auf den ersten Einfügen. Ihr Code scheint sich in einer rekursiven Schleife zu befinden, die eine große Datenmenge verarbeiten kann. Möglicherweise werden viele Abfragen ausgeführt, und die Transaktion läuft ab.

Irgendwann System.Transactions.Transaction.Current hat einige Hinweise auf was passiert ist. Fügen Sie eine Überwachung für diese globale Variable hinzu

+0

Ja meine Haare haben angefangen zu fallen! Ich werde ein Update geben, wie ich mit den obigen Vorschlägen zurecht komme. – Cragly

+2

+1 für "machte meine Haare grau" .. es ist eine wahre Geschichte –

+1

Timeout hat mich ein paar Mal erwischt. Es ist leicht, die verteilte Transaktion zu vergessen, besonders beim Debuggen. Es ist erwähnenswert, dass der Standardwert nur 1 Minute beträgt. Sie können es erhöhen (z. B. auf 10 Minuten), indem Sie dies zu Ihrer app.config - '' hinzufügen oder als Parameter übergeben zu 'TransactionScope()' – Rhumborl

0

Das standardmäßige maximale Zeitlimit beträgt 10 Minuten. Sie können außer Kraft setzen diese in der machine.config ist jedoch:

<configuration> 
    <system.transactions> 
     <machineSettings maxTimeout="00:00:30" /> 
    </system.transactions> 
</configuration> 

Oder Sie können Reflektion verwenden es im Code außer Kraft zu setzen:

private static void OverrideTransactionScopeMaximumTimeout(TimeSpan timeOut) 
    { 

     // 1. create a object of the type specified by the fully qualified name 

     Type oSystemType = typeof(global::System.Transactions.TransactionManager); 

     System.Reflection.FieldInfo oCachedMaxTimeout = oSystemType.GetField("_cachedMaxTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 

     System.Reflection.FieldInfo oMaximumTimeout = oSystemType.GetField("_maximumTimeout", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); 

     oCachedMaxTimeout.SetValue(null, true); 

     oMaximumTimeout.SetValue(null, timeOut); 

     // For testing to confirm value was changed 

     // MessageBox.Show(string.Format(&quot;DEBUG SUCCESS!! &nbsp;Maximum Timeout for transactions is &#39;{0}&#39;&quot;, TransactionManager.MaximumTimeout.ToString())); 

    } 

Weitere Informationen: https://blogs.msdn.microsoft.com/ajit/2008/06/18/override-the-system-transactions-default-timeout-of-10-minutes-in-the-code/

Verwandte Themen