2014-09-23 6 views
13

eccezione completa:Perché SqlAzureExecutionStrategy non gestisce: errore: 19 - Connessione fisica non è utilizzabile

System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for details. ---> System.Data.SqlClient.SqlException: A transport-level error has occurred when receiving results from the server. (provider: Session Provider, error: 19 - Physical connection is not usable)

Perché non è questo gestito dal SqlAzureExecutionStrategy? Soprattutto perché questo accade durante gli scambi VIP.

È una buona idea scrivere un proprio DbExecutionStrategy che gestisce questo, o mi manca qualcosa?

UPDATE mi sono trasferito da Azure Cloud Services a Azure Web Apps e la quantità di volte che vedo questo errore è gravemente caduto.

+4

Spero davvero che qualcuno risponda a questo. È incredibile per me che questo sia "previsto e normale" in Azure, ma SqlAzureExecutionStrategy non gestisce questo particolare errore. –

+0

Segnala il bug. Il progetto è open source. I commit stanno arrivando ogni giorno. – usr

+0

Si tratta di un bug in primo luogo? È qualcosa che accade così spesso che ho la sensazione che sia stata una decisione di progettazione. –

risposta

13

From the profiler trace we observe that the same connection is used for each query database query. This is by design and as discussed early, i.e. when a connection is explicitly opened by the developer it tells EF not to open/reopen a connection for each command.

Beh, questo certamente non sembra una dichiarazione generale. Quale traccia di profiler? Perché supponiamo che la connessione sia stata esplicitamente aperta dallo sviluppatore e gestita dall'EF? Non vedo nulla di simile nella domanda originale (e non è una pratica comune con EF).

Quindi le domande rimangono senza risposta: perché questo non è gestito da SqlAzureExecutionStrategy? È una buona idea scrivere una propria DbExecutionStrategy che gestisca questa?

Poiché è possibile visualizzare questo errore nel servizio di Azure di tanto in tanto, ho deciso di testarlo. Qui è la mia strategia:

public class ExtendedSqlAzureExecutionStrategy : SqlAzureExecutionStrategy 
    { 
     public ExtendedSqlAzureExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) 
     { } 

     protected override bool ShouldRetryOn(Exception exception) 
     { 
      return base.ShouldRetryOn(exception) || IsPhysicalConnectionNotUsableSqlException(exception); 
     } 

     private bool IsPhysicalConnectionNotUsableSqlException(Exception ex) 
     { 
      var sqlException = ex as SqlException; 
      if (sqlException != null) 
      { 
       // Enumerate through all errors found in the exception. 
       foreach (SqlError err in sqlException.Errors) 
       { 
        if (err.Number == 19) 
        { 
         return true; 
        }      
       } 
      } 

      return false; 
     } 
    } 

EDIT

Ok, quindi dopo un po 'di tempo e la registrazione posso dire che basa la strategia su

if (err.Number == 19) 

è sbagliato. L'oggetto SqlException effettivo per questo errore ha ErrorCode = -2146232060 e Number = -1 - Non ho trovato alcuna documentazione per questi, quindi ho deciso di non basare la strategia su di essi. Per ora sto cercando di controllo banale:

public class ExtendedSqlAzureExecutionStrategy : SqlAzureExecutionStrategy 
    { 
     public ExtendedSqlAzureExecutionStrategy(int maxRetryCount, TimeSpan maxDelay) : base(maxRetryCount, maxDelay) 
     { } 

     protected override bool ShouldRetryOn(Exception exception) 
     { 
      return base.ShouldRetryOn(exception) || IsPhysicalConnectionNotUsableSqlException(exception); 
     } 

     private bool IsPhysicalConnectionNotUsableSqlException(Exception ex) 
     { 
      var sqlException = ex as SqlException; 
      if (sqlException != null) 
      { 
       return sqlException.Message.Contains("Physical connection is not usable"); 
      } 

      return false; 
     } 
    } 

EDIT 2:

Funziona. Non più errori Physical connection is not usable e nessun RetryLimitExceededException, quindi questo errore è di fatto transitorio (risolvibile da tentativi), quindi penso che dovrebbe essere incluso in SqlAzureExecutionStrategy.

+0

Grazie mille per aver provato questo. Ti sbatterò in un istante per ricordarti :) qual è il tuo sito? –

+0

Grazie mille per aver provato questo. Penso che implementerò anche questo e farò conoscere i risultati. Spero che un giorno qualcuno della squadra EF (o Azure) possa rispondere ufficialmente a questo. –

+0

ps @rouen, hai anche questo spesso durante gli scambi VIP? –

3

Se la connessione è stata aperta in modo esplicito, questa è una decisione di progettazione. Microsoft dice:

From the profiler trace we observe that the same connection is used for each query database query. This is by design and as discussed early, i.e. when a connection is explicitly opened by the developer it tells EF not to open/reopen a connection for each command. The series of Audit Login/Logout events to retrieve the customer entity or address entity are not submitted as we saw in Case #1 and #2. This means we cannot implement a retry policy for each individual query like I showed earlier. Since the EntityConnection has been assigned to the ObjectContext, EF takes the position that you really truly want to use one connection for all of your queries within the scope of that context. Retrying a query on an invalid or closed connection can never work, a System.Data.EntityCommandExecutionException will be thrown with an inner SqlException contains the message for the error. (see http://blogs.msdn.com/b/appfabriccat/archive/2010/12/11/sql-azure-and-entity-framework-connection-fault-handling.aspx)

Inoltre, e le mie scuse se avete già visto, ma Julia alla Data Farm va in molto di po 'di dettaglio per errori transitori. Non sono sicuro se "La connessione fisica non è utilizzabile" è considerata transitoria - non è inclusa nell'elenco per System.Data.SqlClient.SqlException nel codice per SqlAzureExecutionStrategy - ma potrebbe valere la pena guardare: http://thedatafarm.com/data-access/ef6-connection-resiliency-for-sql-azure-when-does-it-actually-do-its-thing/ (e il suo follow-up, a cui si fa riferimento nel articolo collegato).

Non ho guardato in profondità in Azure dal 2012, ma spero che questo aiuti.

+0

Oops, ho appena notato che ho scritto "avere" invece di "non averlo" in quest'ultima frase. Certamente ha cambiato il significato di quella frase! Risolto il problema con la modifica. – frasnian

1

Physical connection is not usable è una grande categoria di errori, alcuni dei quali sono transitori, ma alcuni non lo sono. SqlAzureExecutionStrategy riprova solo gli errori specifici noti come transitori.

È necessario esaminare tutti i codici contenuti nella raccolta .Errors per determinare se l'azione debba essere ripetuta. Si prega di segnalare se si riscontrano errori transitori ricorrenti specifici a causa di errori SqlAzureExecutionStrategy.

Detto questo, errori generici -1 e -2 possono essere ritentati nella strategia personalizzata dopo aver escluso tutte le possibili cause sotto il vostro controllo: transazioni a esecuzione prolungata, query eccessivamente complesse, troppe connessioni aperte simultaneamente.

0

mia conclusione attuale è questo: l'elenco degli errori in SqlAzureExecutionStrategy è altro che un'ipotesi dal team di Entity Framework; e di solito non è aggiornato poiché l'EF non viene aggiornato in sincronia con SQL Azure.

Baso questa conclusione guardando la cronologia della lista, incluso un errore commentato -2, e confrontandolo con altre liste in altre parti di codice intorno ai blog, il (ora obsoleto) Transient Error Handling Block e gli errori reali sempre mutevoli che stiamo vedendo personalmente.

Fintanto che le due squadre e le codebase sono separate, probabilmente questo approccio non funzionerà. Se hanno reso questa lista di errori transitori una proprietà del server SQL che EF poteva interrogare e utilizzare, e ha reso il lavoro dei team di SQL Azure per mantenerlo aggiornato e accurato, allora forse questa soluzione avrebbe funzionato.

Nel frattempo, la mia conclusione è che l'unica strategia possibile che non si romperà in modo casuale, è quello di riprovare ogni eccezione. Certo, alcuni di loro sono probabilmente inutili per riprovare, ma l'unico modo sicuro è provare.

Problemi correlati