I would like to give my contribution to those who, like me, have encountered this error even though they are not in the situation of having to interact with a database on Azure or on another platform in the cloud.
The first goal is to get to the exact origin of the problem; like me many will have collided with the exception text and a mile-long stack trace string. It was useful for me to process the matryoshkas of the InnerExceptions to get to the real message that the database provider issues before closing the connection (which was active at the time of the message!). Alternatively, if possible, it is sufficient to monitor the transactions towards the database from an external tool that allows you to check any errors connected to the TSQL operations in progress (eg SQL Server Profiler).
In my case the scenario was this: 2 instances of the same program (it is a Windows service) that insert records inside a table. Two peculiarities:
- for Windows services, such as for Form or WPF desktop applications, the life cycle of the DbContext is usually longer and it is possible to link it to the Form being processed rather than keep it active for the entire duration of the project having the foresight to periodically refresh it to clear the cache valued up to that moment;
- the target table has its own auto incremental (integer) key field
In this scenario, concurrently, all services's instances try to write the same table and each write operation performed with EF6 produces a query that has a very particular select within it for retrieving and enhancing the key field it represents identity. Something like this:
INSERT [dbo].[People]([Name]) VALUES (@0)
SELECT [Id], [SomeId]
FROM [dbo].[People]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
My code was:
People entry = new People();
entry.name = "ABCD";
_ctx.Set<People>().Add(entry);
await _ctx.SaveChangesAsync();
This type of writing leads to a situation of concurrency between the two processes (expecially when table have about 5M records), which induce the SQL engine to resolve one request and cancel the other. The interpretation of the calling program is precisely "An exception has been raised that is likely due to a transient failure. If you are connecting to a SQL Azure database consider using SqlAzureExecutionStrategy."
To get around the problem I had to make a waiver on the recovery of the incremental id assigned to the new record, treating the table as a stack and reducing the write operation to a direct insert operation using:
await _ctx.Database.ExecuteSqlCommandAsync("INSERT INTO ....");
Alternatively, it is possible to refine the operation with two write operations that do not involve the EF TSQL parser and also retrieve the identifier assigned to the last added record.