Full exception:
System.Data.Entity.Core.EntityCommandExecutionException: An error occurred while executing the command definition. See the inner exception for de
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.
Well this certainly does not sound like general statement. What profiler trace? Why suppose connection explicitly opened by the developer and handled to the EF? I dont see anything like this in original question (and it is not common practice with EF).
So the questions remain unanswered: Why isn't this handled by the SqlAzureExecutionStrategy? Is it a good idea to write an own DbExecutionStrategy that handles this one?
Since I can see this error in my Azure service from time to time, I decided to test it. Here is my strategy:
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, so after some time and logging I can tell that the strategy based on
if (err.Number == 19)
is wrong. Actual SqlException object for this error has ErrorCode = -2146232060
and Number = -1
- I could not find any documentation for those, so I decided not to base strategy on them. For now I am trying trivial check:
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:
It works. No more Physical connection is not usable
errors at all, and no RetryLimitExceededException, so this error is in fact transient (solvable by retry), so I think it should be included in SqlAzureExecutionStrategy
.