Risolvere gli errori di connessione temporanei nel database SQL e in Istanza gestita di SQL

Si applica a:Database SQL di AzureIstanza gestita di SQL di Azure Synapse Analytics

Questo articolo illustra come evitare, risolvere, diagnosticare e ridurre gli errori di connessione e gli errori temporanei che si verificano nell'applicazione client durante l'interazione con il database SQL di Azure, Istanza gestita di SQL di Azure e Azure Synapse Analytics. Informazioni su come configurare la logica di ripetizione dei tentativi, compilare la stringa di connessione e modificare altre impostazioni di connessione.

Errori temporanei

Un errore temporaneo è un errore la cui causa sottostante si risolverà automaticamente in modo rapido. Una causa occasionale di errori temporanei è costituita dal cambio rapido di risorse hardware da parte del sistema Azure per ottenere un bilanciamento migliore dei diversi carichi di lavoro. La maggior parte di questi eventi di riconfigurazione viene completata in meno di 60 secondi. Durante questo intervallo di riconfigurazione possono verificarsi problemi di connessione al database in Database SQL. Le applicazioni che si connettono al database devono essere sviluppate in modo da prevedere tali errori temporanei. Per gestirli, implementare la logica di ripetizione dei tentativi nel codice anziché mostrarli agli utenti come errori dell'applicazione.

Se il programma client usa ADO.NET, l'errore temporaneo verrà segnalato al programma tramite la generazione di un'eccezione SqlException.

Connessione e comando

Provare a ristabilire la connessione al database SQL o all’Istanza gestita di SQL o stabilirne una nuova, in base a quanto indicato di seguito:

  • Si verifica un errore temporaneo durante un tentativo di connessione

Attendere alcuni secondi e quindi tentare nuovamente la connessione.

  • Si verifica un errore temporaneo durante un comando di una query del database SQL e dell’Istanza gestita di SQL

Non ripetere immediatamente il comando. È invece consigliabile stabilire una nuova connessione dopo un breve intervallo di tempo. Quindi eseguire di nuovo il comando.

Logica di ripetizione dei tentativi per errori temporanei

I programmi client in cui occasionalmente si verifica un errore temporaneo sono più affidabili se contengono una logica di ripetizione dei tentativi. Se il programma comunica con il database in database SQL tramite middleware di terze parti, chiedere al fornitore se il middleware include la logica di ripetizione dei tentativi per errori temporanei.

Principi per la ripetizione dei tentativi

  • Se l'errore è temporaneo, provare a ristabilire la connessione.
  • Non riprovare direttamente a eseguire un'istruzione del database SQL o dell’Istanza gestita di SQL SELECT non riuscita con un errore temporaneo. Stabilire invece una nuova connessione e quindi provare a eseguire di nuovo l'istruzione SELECT.
  • Quando un'istruzione del database SQL o dell’Istanza gestita di SQL UPDATE non riesce con un errore temporaneo, stabilire una nuova connessione prima di provare a eseguire di nuovo l'istruzione UPDATE. La logica di ripetizione dei tentativi deve assicurare il completamento dell'intera transazione di database o il rollback dell'intera transazione.

Altre considerazioni per la ripetizione dei tentativi

  • Un programma batch avviato automaticamente dopo l'orario di lavoro e con completamento previsto prima del mattino può permettersi di attendere a lungo tra i diversi tentativi.
  • Un programma di interfaccia utente deve tenere conto della tendenza degli utenti a desistere dopo un'attesa troppo lunga. La soluzione non deve prevedere nuovi tentativi con intervalli di pochi secondi, perché un criterio simile può inondare il sistema con un numero eccessivo di richieste.

Incremento dell'intervallo tra i tentativi

È consigliabile attendere 5 secondi prima di riprovare. Al primo tentativo con un ritardo inferiore a 5 secondi, si rischia di sovraccaricare il servizio cloud. Per ogni tentativo successivo, aumentare in modo esponenziale il ritardo, fino a un massimo di 60 secondi.

Per i client che usano ADO.NET, è disponibile una discussione sul periodo di blocco in Pool di connessioni (ADO.NET).

È anche possibile che si voglia impostare un numero massimo di nuovi tentativi prima dell'autoterminazione del programma.

Esempi di codice con logica di ripetizione dei tentativi

Esempi di codice di logica di ripetizione dei tentativi sono disponibili in:

Eseguire test sulla logica di ripetizione tentativi

Per testare la logica di ripetizione dei tentativi, è necessario simulare o provocare un errore che può essere corretto mentre il programma è ancora in esecuzione.

Eseguire il test mediante la disconnessione dalla rete

Uno dei modi per testare la logica di ripetizione dei tentativi consiste nel disconnettere il computer client dalla rete mentre il programma è in esecuzione. L'errore è:

  • SqlException.Number = 11001
  • Messaggio: "Host sconosciuto"

Come parte del primo tentativo di ripetizione, è possibile riconnettere il computer client alla rete e quindi tentare di connettersi.

Per semplificare il test, disconnettere il computer dalla rete prima di avviare il programma. Il programma riconoscerà quindi un parametro di runtime che ha le conseguenze seguenti sul programma:

  • Aggiunta temporanea di 11001 al rispettivo elenco di errori da considerare temporanei.
  • Tentativo della prima connessione come di consueto.
  • Dopo il rilevamento dell'errore, rimozione di 11001 dall'elenco.
  • Visualizzazione di un messaggio che richiede all'utente di connettere il computer alla rete.
  • Sospensione delle ulteriori esecuzioni con il metodo Console.ReadLine o una finestra di dialogo con un pulsante OK. L'utente preme il tasto INVIO dopo la connessione del computer alla rete.
  • Nuovo tentativo di connessione, con esito positivo previsto.

Eseguire il test mediante la digitazione non corretta del nome dell’utente durante la connessione

Il programma può intenzionalmente digitare in modo errato il nome utente prima del primo tentativo di connessione. L'errore è:

  • SqlException.Number = 18456
  • Messaggio: "Accesso non riuscito per l'utente 'WRONG_MyUserName'."

Come parte del primo tentativo, il programma può correggere l'errore di digitazione e quindi provare a connettersi.

Per semplificare il test, il programma riconosce un parametro di runtime che ha le conseguenze seguenti sul programma:

  • Aggiunta temporanea di 18456 al rispettivo elenco di errori da considerare temporanei.
  • Aggiunta intenzionale di 'WRONG_' al nome utente.
  • Dopo il rilevamento dell'errore, rimozione di 18456 dall'elenco.
  • Rimozione di 'WRONG_' dal nome utente.
  • Nuovo tentativo di connessione, con esito positivo previsto.

Parametri di SqlConnection di .NET per nuovi tentativi di connessione

Se il programma client si connette al database SQL di Azure usando la classe .NET Framework System.Data.SqlClient.SqlConnection, è necessario usare .NET 4.6.1 o versioni successive (o .NET Core) per poterne sfruttare la funzionalità di ripetizione dei tentativi di connessione. Per ulteriori informazioni su questa funzionalità, vedere Proprietà SqlConnection.ConnectionString.

Quando si crea la stringa di connessione per l'oggetto SqlConnection, coordinare i valori tra i parametri seguenti:

  • ConnectRetryCount: Il valore predefinito è 1. L'intervallo è compreso tra 0 e 255.
  • ConnectRetryInterval: Il valore predefinito è 10 secondi. L'intervallo consentito è tra 1 e 60.
  • Timeout di connessione: Il valore predefinito è 15 secondi. L'intervallo è compreso tra 0 e 2147483647.
  • Timeout di connessione: Il timeout predefinito è 30 secondi. L'intervallo è compreso tra 0 e 2147483647.

Le impostazioni di ripetizione dei tentativi di connessione (ConnectRetryCount e ConnectRetryInterval) si applicano alla resilienza della connessione. La resilienza della connessione include i tipi distinti seguenti:

  • La resilienza della connessione aperta fa riferimento al metodo iniziale SqlConnection.Open o OpenAsync(). Il primo tentativo di connessione viene conteggiato come try zero. ConnectRetryCount si applica ai tentativi successivi. Pertanto, se la connessione zero non riesce (questo potrebbe non verificarsi immediatamente), ConnectRetryInterval viene applicata prima seguita dai successivi tentativi di ConnectRetryCount (e ConnectRetryInterval). Per sfruttare tutti i tentativi, la proprietà Timeout connessione deve fornire tempo per tutti i tentativi.

  • La resilienza della connessione inattiva si riferisce al rilevamento automatico e alla riconnessione delle connessioni inattive esistenti interrotte. Il primo tentativo di riconnettere una connessione inattiva viene conteggiato come primo tentativo di ripetizione. Per sfruttare tutti i tentativi, il Timeout comando deve fornire tempo per tutti i tentativi.

Esempio: si supponga che i valori seguenti per i parametri ConnectRetryCount e ConnectRetryInterval:

ConnectRetryCount: 3 ConnectRetryInterval: 10 secondi

Vedere come vengono usati questi valori negli scenari seguenti:

Scenario: Nuova connessione

4:10:00 - Connection.Open() - tentativo zero

4:10:01 - Errore di connessione rilevato

4:10:11 - Riprova 1 -> Il primo tentativo si verifica dopo ConnectRetryInterval

4:10:21 - Riprova 2

4:10:31 - Riprova 3

Per questo scenario i valori scelti devono soddisfare la condizione seguente:
Connection Timeout > = ConnectRetryCount * ConnectionRetryInterval

Ad esempio, se numero = 3 e intervallo = 10 secondi, un timeout di soli 29 secondi non garantisce al sistema il tempo sufficiente per il terzo tentativo e il tentativo di connessione finale:

29 < 3 * 10

Scenario: connessione inattiva

ConnectRetryCount: 3 ConnectRetryInterval: 10 secondi

4:10:00 - Connessione interrotta rilevata all'esecuzione del comando

4:10:00 - Riprova 1 -->Primo tentativo si verifica immediatamente

4:10:10 - Riprova 2

4:10:20 - Riprova 3

Questa non è la connessione iniziale. Pertanto, Timeout connessione non si applica. Tuttavia, poiché il ripristino della connessione si verifica durante l'esecuzione del comando, viene applicata l'impostazione Timeout comando. Il Timeout comando predefinito è di 30 secondi. Anche se in circostanze tipiche il ripristino della connessione è veloce, un'interruzione intermittente potrebbe richiedere un certo tempo di esecuzione del comando.

Per questa situazione, se si vuole sfruttare appieno i tentativi di ripristino di connessione inattivi, i valori scelti devono soddisfare la condizione seguente:
Command Timeout > (ConnectRetryCount - 1) * ConnectionRetryInterval

Ad esempio, se il conteggio è 3 e l'intervallo è di 10 secondi, un valore di timeout comando inferiore a 20 secondi non darebbe tempo sufficiente per il terzo tentativo finale di connessione: (3 - 1) * 10 = 20'

Tenere inoltre presente che, dopo il ripristino della connessione, l’esecuzione del comando stesso richiede del tempo.

Nota

I valori di durata forniti in questi scenari sono solo a scopo dimostrativo. I tempi di rilevamento effettivi in entrambi gli scenari dipendono dall'infrastruttura sottostante.

Connessione e comando

I parametri ConnectRetryCount e ConnectRetryInterval consentono all'oggetto SqlConnection di ripetere l'operazione di connessione senza interferire con il programma, ad esempio per restituire il controllo al programma. I tentativi possono verificarsi nelle situazioni seguenti:

  • Chiamata metodo SqlConnection.Open
  • Chiamata metodo SqlConnection.Execute

È importante sottolineare che, se si verifica un errore temporaneo durante l'esecuzione della query, l'oggetto SqlConnection non ripete l'operazione di connessione e certamente non ritenta l'esecuzione della query. Prima di inviare la query per l'esecuzione, tuttavia, SqlConnection controlla rapidamente la connessione e, se viene rilevato un problema, SqlConnection ritenta l'operazione di connessione. Se il tentativo ha esito positivo, la query viene inviata per l'esecuzione.

Opportunità di combinare ConnectRetryCount con la logica di ripetizione dei tentativi nell'applicazione

Si supponga che l'applicazione disponga di una logica di ripetizione dei tentativi particolarmente avanzata, in cui l'operazione di connessione può essere ritentata fino a quattro volte. Se si aggiunge ConnectRetryInterval e ConnectRetryCount = 3 alla stringa di connessione, il numero dei tentativi aumenterà a 4 * 3 = 12 tentativi. Un numero così elevato di tentativi potrebbe non essere consigliabile.

Connessioni al database nel database SQL di Azure

Connessione: stringa di connessione

La stringa di connessione necessaria per connettersi al database SQL è leggermente diversa rispetto alla stringa usata per connettersi a SQL Server. È possibile copiare la stringa di connessione per il database dal portale di Azure.

Ottenere la stringa di connessione dal portale di Azure

Usare il portale di Azure per ottenere la stringa di connessione necessaria al programma client per interagire con il database SQL di Azure.

  1. Selezionare Tutti i servizi>Database SQL.

  2. Immettere il nome del database nella casella di testo di filtro vicino alla parte superiore sinistra del pannello Database SQL.

  3. Selezionare la riga per il database.

  4. Quando viene visualizzato il pannello del database, per una visualizzazione più chiara selezionare i pulsanti Riduci a icona per comprimere i pannelli usati per la ricerca e il filtro del database.

  5. Nel pannello del database selezionare Mostra stringhe di connessione del database.

  6. Copiare la stringa di connessione appropriata. Se ad esempio si prevede di usare la libreria di connessione ADO.NET, copiare la stringa appropriata dalla scheda ADO.NET.

    Copy the ADO connection string for your database

  7. Modificare la stringa di connessione in base alle esigenze. Inserire la password nella stringa di connessione o rimuovere "@<servername>" dal nome utente se il nome utente o il nome server è troppo lungo.

  8. In un formato o un altro, incollare le informazioni sulla stringa di connessione nel codice del programma client.

Per altre informazioni, vedere Stringhe di connessione e file di configurazione.

Connessione: indirizzo IP

È necessario configurare il database SQL in modo che accetti le comunicazioni dall'indirizzo IP del computer che ospita il programma client. Per impostare questa configurazione, modificare le impostazioni del firewall tramite il portale di Azure.

Se si dimentica di configurare l'indirizzo IP, il programma restituirà un messaggio di errore che indica la necessità dell'indirizzo IP.

  1. Accedere al portale di Azure.

  2. Nell'elenco a sinistra selezionare Tutti i servizi.

  3. Scorrere e selezionare SQL Server.

    Find your Azure SQL Database server in the portal

  4. Nella casella di testo di filtro, iniziare a digitare il nome del server. Viene visualizzata la riga.

  5. Selezionare la riga per il server. Viene visualizzato un pannello per il server.

  6. Nel pannello del server, selezionare Impostazioni.

  7. Selezionare Firewall.

    Select Settings > Firewall

  8. Selezionare Aggiungi IP client. Digitare un nome per la nuova regola nella prima casella di testo.

  9. Digitare i valori di indirizzo IP minimo e massimo per l'intervallo che si desidera abilitare.

    • Può essere utile impostare come fine del valore minimo .0 e come fine del valore massimo su .255.
  10. Seleziona Salva.

Per altre informazioni, vedere Configurare le impostazioni del firewall nel database SQL.

Connessione: porte

In genere è sufficiente assicurarsi che soltanto la porta 1433 sia aperta per le comunicazioni in uscita sul computer che ospita il programma client.

Ad esempio, se il programma client è ospitato in un computer Windows, è possibile usare Windows Firewall nell'host per aprire la porta 1433.

  1. Aprire il Pannello di controllo.
  2. Selezionare Tutti gli elementi del Pannello di controllo>Windows Firewall>Impostazioni avanzate>Regole in uscita>Azioni>Nuova regola.

Se il programma client si trova su una macchina virtuale (VM) di Azure, leggere Porte superiori a 1433 per ADO.NET 4.5 e il database SQL.

Per informazioni generali sulla configurazione di porte e indirizzi IP nel database, vedere Firewall del database SQL di Azure.

Connessione: ADO.NET 4.6.2 o versioni successive

Se il programma usa classi ADO.NET come System.Data.SqlClient.SqlConnection per la connessione al database SQL, è consigliabile usare .NET Framework 4.6.2 o versioni successive.

A partire da ADO.NET 4.6.2

  • L'apertura della connessione viene ritentata immediatamente per Azure SQL, migliorando così le prestazioni delle App abilitate per il cloud.

A partire da ADO.NET 4.6.1

  • Per il database SQL, è possibile migliorare l'affidabilità aprendo una connessione con il metodo SqlConnection.Open. Il metodo Open incorpora ora meccanismi di ripetizione dei tentativi di tipo "massimo sforzo" in risposta agli errori temporanei, per alcuni errori entro l'intervallo di durata della connessione.
  • È supportato il pool di connessioni, inclusa una verifica efficiente del corretto funzionamento dell'oggetto connessione fornito al programma.

Quando si usa un oggetto connessione da un pool di connessioni, è consigliabile che il programma chiuda temporaneamente la connessione se questa non deve essere usata immediatamente. Riaprire una connessione non ha alcun costo, a differenza della creazione di una nuova connessione.

Se si usa ADO.NET 4.0 o versioni precedenti, è consigliabile eseguire l'aggiornamento alla versione più recente di ADO.NET. A partire da agosto 2018, è possibile scaricare ADO.NET 4.6.2.

Diagnostica

Diagnostica: verificare se le utilità si possono connettere

Se il programma non riesce a connettersi al database nel database SQL, un'opzione di diagnostica consente di provare a connettersi mediante un programma di utilità. Idealmente l'utilità si connette mediante la stessa libreria usata dal programma.

In qualsiasi computer Windows è possibile provare queste utilità:

  • SQL Server Management Studio (ssms.exe), che si connette tramite ADO.NET
  • sqlcmd.exe, che si connette tramite ODBC

Dopo la connessione del programma, verificare il funzionamento di una breve query SQL SELECT.

Diagnostica: verificare le porte aperte

Se si ritiene che i tentativi di connessione abbiano esito negativo a causa di problemi di porta, è possibile eseguire sul computer un'utilità che segnala le configurazioni delle porte.

In Linux possono risultare utili le utilità seguenti:

  • netstat -nap
  • nmap -sS -O 127.0.0.1: modificare il valore di esempio con il proprio indirizzo IP.

In Windows è possibile usare l'utilità PortQry.exe. Ecco un'esecuzione di esempio che ha eseguito una query relativa alla situazione delle porte in un database nel database SQL e che è stata eseguita in un computer portatile:

[C:\Users\johndoe\]
>> portqry.exe -n johndoesvr9.database.windows.net -p tcp -e 1433

Querying target system called: johndoesvr9.database.windows.net

Attempting to resolve name to IP address...
Name resolved to 23.100.117.95

querying...
TCP port 1433 (ms-sql-s service): LISTENING

[C:\Users\johndoe\]
>>

Diagnostica: registrare gli errori

La diagnosi di un problema intermittente è spesso agevolata dal rilevamento di uno schema generale nel corso di giorni o settimane.

Il client può supportare l'analisi tramite la registrazione di tutti gli errori rilevati. È possibile che si riesca a correlare le voci del log con i dati di errore registrati internamente dal database SQL.

Enterprise Library 6 (EntLib60) offre classi .NET gestite per semplificare la registrazione. Per altre informazioni, vedere 5 - Più facile che mai: uso del blocco applicazione di registrazione.

Diagnostica: cercare errori nei log di sistema

Ecco alcune istruzioni Transact-SQL SELECT che eseguono query nei log degli errori e alla ricerca di altre informazioni.

Query di un log Descrizione
SELECT e.*
FROM sys.event_log AS e
WHERE e.database_name = 'myDbName'
AND e.event_category = 'connectivity'
AND 2 >= DateDiff
  (hour, e.end_time, GetUtcDate())
ORDER BY e.event_category,
  e.event_type, e.end_time;
La visualizzazione sys.event_log offre informazioni sui singoli eventi, inclusi quelli che possono causare errori temporanei o di connettività.

In teoria, è possibile correlare i valori start_time o end_time con le informazioni relative al momento in cui si sono verificati problemi nel programma client.

È necessario connettersi al database master per eseguire questa query.
SELECT c.*
FROM sys.database_connection_stats AS c
WHERE c.database_name = 'myDbName'
AND 24 >= DateDiff
  (hour, c.end_time, GetUtcDate())
ORDER BY c.end_time;
La vista sys.database_connection_stats offre un conteggio aggregato dei tipi di evento, per consentire operazioni di diagnostica aggiuntive.

È necessario connettersi al database master per eseguire questa query.

Diagnostica: cercare eventi relativi a problemi nel log del database SQL

È possibile cercare voci relative agli eventi problematici nel log del database SQL. Provare a eseguire l'istruzione Transact-SQL SELECT seguente nel database master :

SELECT
   object_name
  ,CAST(f.event_data as XML).value
      ('(/event/@timestamp)[1]', 'datetime2')                      AS [timestamp]
  ,CAST(f.event_data as XML).value
      ('(/event/data[@name="error"]/value)[1]', 'int')             AS [error]
  ,CAST(f.event_data as XML).value
      ('(/event/data[@name="state"]/value)[1]', 'int')             AS [state]
  ,CAST(f.event_data as XML).value
      ('(/event/data[@name="is_success"]/value)[1]', 'bit')        AS [is_success]
  ,CAST(f.event_data as XML).value
      ('(/event/data[@name="database_name"]/value)[1]', 'sysname') AS [database_name]
FROM
  sys.fn_xe_telemetry_blob_target_read_file('el', null, null, null) AS f
WHERE
  object_name != 'login_event'  -- Login events are numerous.
  and
  '2015-06-21' < CAST(f.event_data as XML).value
        ('(/event/@timestamp)[1]', 'datetime2')
ORDER BY
  [timestamp] DESC
;

Alcune righe restituite da sys.fn_xe_telemetry_blob_target_read_file

Nell'esempio seguente viene illustrato il possibile aspetto di una riga restituita. I valori Null mostrati sono spesso non Null in altre righe.

object_name                   timestamp                    error  state  is_success  database_name

database_xml_deadlock_report  2015-10-16 20:28:01.0090000  NULL   NULL   NULL        AdventureWorks

Enterprise Library 6

Enterprise Library 6 (EntLib60) è un framework di classi .NET che semplifica l'implementazione di client affidabili dei servizi cloud, ad esempio il database SQL. Gli argomenti dedicati a ogni area per cui EntLib60 può risultare utile sono disponibili in Enterprise Library 6 - Aprile 2013.

Logica di ripetizione dei tentativi per la gestione degli errori temporanei è un'area in cui EntLib60 può essere utile. Per altre informazioni, vedere 4 - Perseveranza, il segreto di tutti i successi: uso del Blocco di applicazioni per la gestione degli errori temporanei.

Nota

Il codice sorgente per EntLib60 è disponibile per il download pubblico nell'Area download. Microsoft non prevede di fornire altre funzionalità o aggiornamenti di manutenzione per EntLib.

Classi di EntLib60 per errori temporanei e ripetizione dei tentativi

Le classi seguenti di EntLib60 sono particolarmente utili per la logica di ripetizione dei tentativi. Tutte queste classi sono disponibili nello spazio dei nomi Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling o nei livelli sottostanti.

Nello spazio dei nomi Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling:

  • Classe RetryPolicy
    • ExecuteAction
  • classe ExponentialBackoff
  • SqlDatabaseTransientErrorDetectionStrategy
  • Classe ReliableSqlConnection
    • ExecuteCommand

Nello spazio dei nomi Microsoft.Practices.EnterpriseLibrary.TransientFaultHandling.TestSupport:

  • AlwaysTransientErrorDetectionStrategy
  • NeverTransientErrorDetectionStrategy

Ecco alcuni collegamenti alle informazioni relative a EntLib60:

EntLib60: il blocco di registrazione

  • Il blocco di registrazione è una soluzione a flessibilità e configurabilità elevata che consente di:
    • Creare e archiviare messaggi di log in diverse posizioni.
    • Classificare e filtrare i messaggi.
    • Raccogliere informazioni contestuali utili per il debug e la traccia, oltre che per i requisiti di controllo e di registrazione generale.
  • Il blocco di registrazione astrae la funzionalità di registrazione dalla destinazione di registrazione, in modo che il codice applicazione sia coerente, indipendentemente dalla posizione e dal tipo di archivio di registrazione di destinazione.

Per altre informazioni, vedere 5 - Più facile che mai: uso del blocco applicazione di registrazione.

Codice sorgente del metodo IsTransient di EntLib60

La classe SqlDatabaseTransientErrorDetectionStrategy include anche il codice sorgente C# per il metodo IsTransient. Il codice sorgente chiarisce gli errori considerati temporanei e idonei alla ripetizione dei tentativi, a partire da aprile 2013.

public bool IsTransient(Exception ex)
{
  if (ex != null)
  {
    SqlException sqlException;
    if ((sqlException = ex as SqlException) != null)
    {
      // Enumerate through all errors found in the exception.
      foreach (SqlError err in sqlException.Errors)
      {
        switch (err.Number)
        {
            // SQL Error Code: 40501
            // The service is currently busy. Retry the request after 10 seconds.
            // Code: (reason code to be decoded).
          case ThrottlingCondition.ThrottlingErrorNumber:
            // Decode the reason code from the error message to
            // determine the grounds for throttling.
            var condition = ThrottlingCondition.FromError(err);

            // Attach the decoded values as additional attributes to
            // the original SQL exception.
            sqlException.Data[condition.ThrottlingMode.GetType().Name] =
              condition.ThrottlingMode.ToString();
            sqlException.Data[condition.GetType().Name] = condition;

            return true;

          case 10928:
          case 10929:
          case 10053:
          case 10054:
          case 10060:
          case 40197:
          case 40540:
          case 40613:
          case 40143:
          case 233:
          case 64:
            // DBNETLIB Error Code: 20
            // The instance of SQL Server you attempted to connect to
            // does not support encryption.
          case (int)ProcessNetLibErrorCode.EncryptionNotSupported:
            return true;
        }
      }
    }
    else if (ex is TimeoutException)
    {
      return true;
    }
    else
    {
      EntityException entityException;
      if ((entityException = ex as EntityException) != null)
      {
        return this.IsTransient(entityException.InnerException);
      }
    }
  }

  return false;
}

Passaggi successivi