title: Entity Framework 6 Timeout exception and retry but the query succeeded
body: <p>We are using Entity Framework 6.1.2 in an Azure Cloud Service.
  We have added both the RetryStrategy and the CommitFailureHandler.</p>
  
  <p>When a request is received we are trying to insert a new row into a table using the raw SQL part of Entity Framework.</p>
  
  <p>We first check to see if the row exists for the ID we want to insert.</p>
  
  <pre><code>var rows = dbContext.Database.SqlQuery&lt;T&gt;(
      "SELECT * FROM FactState WHERE ID = @p0 ", ID
  ).ToList();
  
  return rows != null;
  </code></pre>
  
  <p>If it doesn't exist then we insert the row</p>
  
  <pre><code>dbContext.Database.ExecuteSqlCommand(
      "INSERT INTO FactState ( ID, Value ) VALUES( @p0, @p1 )",
      ID,
      Value
  );
  </code></pre>
  
  <p>Every once in a while the insert query is throwing a Timeout exception which the retry strategy correctly retries.
  On the retry however the query throws a Primary Key Violation for each retry until it reaches the limit of 5.</p>
  
  <p>Now my question is how does this happen.
  I would have expected a Timeout exception to result in the rows not being added at all, or if the exception occurred during the Commit phase then the commit failure handler would have run and correctly identified the query had succeeded.</p>
  
  <p>I have stepped through the source of Entity Framework in a test program, I can simulate the behavior by manually inserting the row after forcing a timeout with table locks.
  But I don't understand how it can happen in our production environment.</p>
  
  <p><strong>Update</strong></p>
  
  <p>The time out exception has happened multiple times again over the weekend. The exception is happening inside the commit process but this means the commit failure handler is not being run. I suppose its possible the commit failure handler is not attached at the time the commit is running, however I don't understand how given I am using the following code to add the commit failure handler</p>
  
  <pre><code>public class MyConfiguration : DbConfiguration
  {
      public MyConfiguration()
      {
          this.SetExecutionStrategy(
              "System.Data.SqlClient",
              () =&gt; new SqlAzureExecutionStrategy());
  
          this.SetTransactionHandler(
              SqlProviderServices.ProviderInvariantName,
              () =&gt; new CommitFailureHandler());
      }
  }
  </code></pre>
  
  <p>I have attached a stack trace when the error occurred</p>
  
  <pre><code>Exception: System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.  This failure occurred while attempting to connect to the routing destination. The duration spent while attempting to connect to the original server was - [Pre-Login] initialization=1; handshake=18; [Login] initialization=0; authentication=0; [Post-Login] complete=1;   ---&gt; System.ComponentModel.Win32Exception (0x80004005): The wait operation timed out
  at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
  at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
  at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
  at System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync()
  at System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket()
  at System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer()
  at System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte&amp; value)
  at System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean&amp; dataReady)
  at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
  at System.Data.SqlClient.TdsParser.TdsExecuteTransactionManagerRequest(Byte[] buffer, TransactionManagerRequestType request, String transactionName, TransactionManagerIsolationLevel isoLevel, Int32 timeout, SqlInternalTransaction transaction, TdsParserStateObject stateObj, Boolean isDelegateControlRequest)
  at System.Data.SqlClient.SqlInternalConnectionTds.ExecuteTransactionYukon(TransactionRequest transactionRequest, String transactionName, IsolationLevel iso, SqlInternalTransaction internalTransaction, Boolean isDelegateControlRequest)
  at System.Data.SqlClient.SqlInternalTransaction.Commit()
  at System.Data.SqlClient.SqlTransaction.Commit()
  at System.Data.Entity.Infrastructure.Interception.InternalDispatcher`1.Dispatch[TTarget,TInterceptionContext](TTarget target, Action`2 operation, TInterceptionContext interceptionContext, Action`3 executing, Action`3 executed)
  at System.Data.Entity.Infrastructure.Interception.DbTransactionDispatcher.Commit(DbTransaction transaction, DbInterceptionContext interceptionContext)
  at System.Data.Entity.Core.EntityClient.EntityTransaction.Commit()
  </code></pre>