Condividi tramite


Gestione degli errori di commit delle transazioni

Nota

EF6.1 Solo versioni successive: le funzionalità, le API e così via sono state introdotte in Entity Framework 6.1. Se si usa una versione precedente, le informazioni qui riportate, o parte di esse, non sono applicabili.

Nell'ambito della versione 6.1 è stata introdotta una nuova funzionalità di resilienza della connessione per Entity Framework: la possibilità di rilevare e ripristinare automaticamente quando gli errori di connessione temporanei influiscono sul riconoscimento dei commit delle transazioni. I dettagli completi dello scenario sono descritti meglio nel post di blog database SQL Connessione ivity e il problema di Idempotency. In sintesi, lo scenario è che quando viene generata un'eccezione durante un commit della transazione esistono due possibili cause:

  1. Commit della transazione non riuscito nel server
  2. Il commit della transazione è riuscito nel server, ma un problema di connettività ha impedito che la notifica di esito positivo raggiunga il client

Quando si verifica la prima situazione, l'applicazione o l'utente può ritentare l'operazione, ma quando si verifica la seconda situazione è consigliabile evitare nuovi tentativi e l'applicazione potrebbe ripristinarsi automaticamente. La sfida è che senza la possibilità di rilevare il motivo effettivo per cui è stata segnalata un'eccezione durante il commit, l'applicazione non può scegliere il corso di azione corretto. La nuova funzionalità di EF 6.1 consente a ENTITY Framework di verificare con il database se la transazione ha avuto esito positivo e di intraprendere la giusta azione in modo trasparente.

Uso della funzionalità

Per abilitare la funzionalità necessaria, includere una chiamata a SetTransactionHandler nel costruttore di DbConfiguration. Se non si ha familiarità con DbConfiguration, vedere Configurazione basata su codice. Questa funzionalità può essere usata in combinazione con i tentativi automatici introdotti in EF6, che aiutano nella situazione in cui la transazione effettivamente non è riuscita a eseguire il commit sul server a causa di un errore temporaneo:

using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.SqlServer;

public class MyConfiguration : DbConfiguration  
{
  public MyConfiguration()  
  {  
    SetTransactionHandler(SqlProviderServices.ProviderInvariantName, () => new CommitFailureHandler());  
    SetExecutionStrategy(SqlProviderServices.ProviderInvariantName, () => new SqlAzureExecutionStrategy());  
  }  
}

Modalità di rilevamento delle transazioni

Quando la funzionalità è abilitata, Entity Framework aggiungerà automaticamente una nuova tabella al database denominato __Transactions. In questa tabella viene inserita una nuova riga ogni volta che viene creata una transazione da Entity Framework e tale riga viene verificata se si verifica un errore di transazione durante il commit.

Anche se EF eseguirà un'operazione ottimale per eliminare le righe dalla tabella quando non sono più necessarie, la tabella può aumentare se l'applicazione viene chiusa prematuramente e per questo motivo potrebbe essere necessario ripulire manualmente la tabella in alcuni casi.

Come gestire gli errori di commit con le versioni precedenti

Prima di EF 6.1 non esiste alcun meccanismo per gestire gli errori di commit nel prodotto EF. Esistono diversi modi per gestire questa situazione che possono essere applicate alle versioni precedenti di EF6:

  • Opzione 1 - Non eseguire alcuna operazione

    La probabilità di un errore di connessione durante il commit della transazione è bassa, pertanto può essere accettabile che l'applicazione non riesca se questa condizione si verifica effettivamente.

  • Opzione 2 : usare il database per reimpostare lo stato

    1. Rimuovere il DbContext corrente
    2. Creare un nuovo DbContext e ripristinare lo stato dell'applicazione dal database
    3. Informare l'utente che l'ultima operazione potrebbe non essere stata completata correttamente
  • Opzione 3 - Tenere traccia manuale della transazione

    1. Aggiungere una tabella non rilevata al database usato per tenere traccia dello stato delle transazioni.
    2. Inserire una riga nella tabella all'inizio di ogni transazione.
    3. Se la connessione non riesce durante il commit, verificare la presenza della riga corrispondente nel database.
      • Se la riga è presente, continuare normalmente, perché è stato eseguito correttamente il commit della transazione
      • Se la riga è assente, usare una strategia di esecuzione per ritentare l'operazione corrente.
    4. Se il commit ha esito positivo, eliminare la riga corrispondente per evitare la crescita della tabella.

Questo post di blog contiene codice di esempio per eseguire questa operazione in SQL Azure.