Handling of Transaction Commit Failures
As part of 6.1 we are introducing a new connection resiliency feature for EF: the ability to detect and recover automatically when transient connection failures affect the acknowledgement of transaction commits. The full details of the scenario are best
described in Issue #1114 and in the blog post
SQL Database Connectivity and the Idempotency Issue. In summary, the scenario is that when an exception is raised during a transaction commit there are two possible causes:
- The transaction commit failed on the server
- The transaction commit succeeded on the server but a connectivity issue prevented the success notification from reaching the client
When the first situation happens the application or the user can retry the operation, but when the second situation occurs retries should be avoided and the application could recover automatically. The challenge is that without the ability to detect what
was the actual reason an exception was reported during commit, the application cannot choose the right course of action. The new feature allows EF to double-check with the database if the transaction succeeded and take the right course of action transparently.
Using the feature
In order to enable the feature you need include a call to SetTransactionHandler in the constructor of your DbConfiguration. The new feature can be used in combination with the automatic retries we introduced in EF6, which help in the situation in which the
transaction actually failed to commit on the server due to a transient failure:
public class MyConfiguration : DbConfiguration
SetTransactionHandler("System.Data.SqlClient", () => new CommitFailureHandler());
SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
How transactions are tracked
When the feature is enabled, EF will automatically add a new table to the database called “__Transactions”. A new row is inserted in this table every time a transaction is created by EF and that row is checked for existence if a transaction failure
occurs during commit.
Although EF will do a best effort to prune rows from the table when they aren’t needed anymore, the table can grow if the application exists prematurely and for that reason you may need to purge the table manually in some cases.