Entity Framework DbExecutionStrategy (connection resiliency) with dotConnect for Oracle
Posted: Mon 25 Feb 2019 19:45
I'm currently working on an EF6 based project with dotConnect version 9.6.696.0 against an Oracle 11g database using direct mode. I tried implementing connection resiliency with DbExecutionStrategy. I created a custom implementation that parses the oracle exception, and looks for certain error codes.
What I notice is that ShouldRetryOn() in the strategy is not called on the first "hit" to the database with Entity Framework and dotConnect for Oracle. On the first call, if the database is unavailable (suppose the service is turned off), the exception will just be thrown to the calling code, and execution will never enter ShouldRetryOn(). The ShouldRetryOn() method is only reached after a successful command/query has been made to the database, and subsequent ones fail (e.g. make 1 query, then turn off the Oracle Service, and try it again. On the second time, ShouldRetryOn() will get executed). The behavior with the standard System.Data.SqlClient provider is different; it will fall into ShouldRetryOn() to determine if it should retry the exception on the first call to the database. The SqlClient behavior is substantially easier to work with in that calls around the EF context do not have to be wrapped in the execution strategy (unless working with a user initiated transaction). From what I'm seeing with the dotConnect Oracle provider, in order to retry any call to the database, I need to manually wrap the code as follows:
Is there any way to make the dotConnect Oracle provider behave in the same way as the Sql Server provider? Will this behave in a different manner if not using a direct connection? Is it dependent on Oracle version? Or is it just how it works?
I created a sample unit test project that distills it down to a very simple model/EF code first context, a simple retry strategy that attempts to always retry the exception, and a few simple tests with instructions to illustrate the problem. It can be downloaded here. just change the app.config for your own connection strings.
What I notice is that ShouldRetryOn() in the strategy is not called on the first "hit" to the database with Entity Framework and dotConnect for Oracle. On the first call, if the database is unavailable (suppose the service is turned off), the exception will just be thrown to the calling code, and execution will never enter ShouldRetryOn(). The ShouldRetryOn() method is only reached after a successful command/query has been made to the database, and subsequent ones fail (e.g. make 1 query, then turn off the Oracle Service, and try it again. On the second time, ShouldRetryOn() will get executed). The behavior with the standard System.Data.SqlClient provider is different; it will fall into ShouldRetryOn() to determine if it should retry the exception on the first call to the database. The SqlClient behavior is substantially easier to work with in that calls around the EF context do not have to be wrapped in the execution strategy (unless working with a user initiated transaction). From what I'm seeing with the dotConnect Oracle provider, in order to retry any call to the database, I need to manually wrap the code as follows:
Code: Select all
var executionStrategy = new AlwaysRetryStrategy();
executionStrategy.Execute(() =>
{
using(var context = new ToDoContext())
{
var count = context.ToDos.Count();
}
});
I created a sample unit test project that distills it down to a very simple model/EF code first context, a simple retry strategy that attempts to always retry the exception, and a few simple tests with instructions to illustrate the problem. It can be downloaded here. just change the app.config for your own connection strings.