Domanda

nel nostro progetto attuale stiamo usando ADO.NET Entity Framework come livello dati per l'applicazione. Ci sono alcune attività che richiedono di essere eseguite in una transazione perché c'è molto lavoro da fare nel database. Sto utilizzando un TransactionScope per circondare tali compiti.

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

Il problema si verifica non appena utilizzo un TransactionScope si verifica un'eccezione:

  

System.Data.EntityException: il provider sottostante non è riuscito su Open. --- > System.Transactions.TransactionManagerCommunicationException: comunicazione con il gestore delle transazioni sottostante non riuscita. --- > System.Runtime.InteropServices.COMException (0x80004005): errore HRESULT E_FAIL è stato restituito da una chiamata a un componente COM.

Sembra che questo errore abbia a che fare con MSDTC (Microsoft Distributed Transaction Coordinator). Quando cambio la configurazione di sicurezza di MSDTC viene generata un'altra eccezione:

  

System.Data.EntityException: il provider sottostante non è riuscito su Open. --- > System.Transactions.TransactionManagerCommunicationException: l'accesso alla rete per Distributed Transaction Manager (MSDTC) è stato disabilitato. Abilitare DTC per l'accesso alla rete nella configurazione di sicurezza per MSDTC utilizzando lo strumento amministrativo Servizi componenti.

Tuttavia, MSDTC è configurato, TransactionScope causerà un errore. Qualcuno sa che cosa non va qui?

È stato utile?

Soluzione 8

Hmm, sembra funzionare quando cambio TransactionScopeOption per " Sopprimere " ;:

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

Tutti sanno perché?

Altri suggerimenti

Per impostazione predefinita, MSDTC ha l'accesso alla rete disabilitato. Per farlo funzionare dovresti andare su

  

Pannello di controllo- > Amministrativo   Strumenti- > Component Services- > Component   Servizi- > Calcola- > Il mio computer- & Gt; giusto   click-> Properties- > > MSDTC-; Sicurezza   Configurazione

e selezionare le seguenti caselle Accesso DTC alla rete, Consenti in entrata, Consenti in uscita. L'autenticazione deve essere scelta in base al proprio ambiente. Potresti anche dare un'occhiata a Strumento DTCP per eseguire il debug delle transazioni distribuite. Per darti una scorciatoia, potrebbe essere necessario modificare il registro:

  

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

per rendere tutto funzionante.

Sì, funziona usando Supress, perché gli stai dicendo di sopprimere o ignorare la transazione ambientale e creare una nuova transazione locale. Poiché la transazione è locale, non è una transazione distribuita, quindi non utilizza MSDTC, ma probabilmente non dovresti usare Suppress e dovresti invece utilizzare Required.

Ciò significa che sta sopprimendo qualsiasi Transazione che potrebbe essere attualmente in vigore quando si inserisce il blocco di codice, quindi eventuali aggiornamenti apportati dal codice non verranno ripristinati se il valore "ambientale" esterno la transazione decide di eseguire il rollback.

Questo è l'articolo che abbiamo usato per risolvere il nostro problema simile:

Risoluzione dei problemi relativi a MSDTC

Questa è sostanzialmente un'aggiunta alla la risposta di Nikolay R . Ha già trattato alcuni dei suggerimenti elencati nell'articolo.

Nota: l'articolo fa parte della documentazione di Biztalk, ma può applicarsi a tutto ciò che utilizza MSDTC.

" Se si utilizza Entity Framework con Transazioni, Entity Framework apre e chiude automaticamente una connessione con ogni chiamata al database. Pertanto, quando si utilizzano le transazioni, si sta tentando di distribuire una transazione su più connessioni. Ciò equivale a MSDTC. & Quot;

È possibile passare nel contesto del database per chiamare classe o funzione nella transazione.

Forse questa è la tua risposta: Errore MSSQL 'Il provider sottostante non è riuscito su Open'

Sopprimere la transazione è utile se si desidera eseguire un codice che potrebbe non riuscire, ma non si desidera interrompere la transazione a causa di tale errore.

La domanda che devi porsi è la seguente: Stai accedendo a più di 1 risorsa durevole in tueopeScope? Voglio dire, apri connessioni a più di 1 DB?

Questa è una domanda importante poiché la transazione verrà intensificata verso DTC se si accede a più di una risorsa durevole.

Nella transazione sono incluse almeno due risorse permanenti che supportano le notifiche monofase. Ad esempio, l'inserimento di una singola connessione con non comporta la promozione di una transazione. Tuttavia, ogni volta che si apre una seconda connessione a un database che causa l'arruolamento del database, l'infrastruttura System.Transactions rileva che è la seconda risorsa duratura nella transazione e la converte in una transazione MSDTC. Fonte: MSDN

In tal caso, è possibile risolvere il problema annidando correttamente i propri transcopi, ad esempio:

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

}

Puoi trovare maggiori informazioni su TransactionScopes, come funziona l'annidamento, ... su MSDN .

Spero che questa risposta possa aiutare le persone in futuro.

Se il servizio Distributed Transaction Coordinator non viene avviato, il framework Entity non può connettersi al database. Apri e avvia il Distributed Transaction Coordinator

Servizi - > Coordinatore delle transazioni distribuite

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top