One category of frequent support questions that we receive is regarding the ADO.NET driver version used to communicate with the database. Various problems related to resolving the appropriate driver are reported and it can be a cause of considerable frustration to the user. Beginning with the Q2 2011 version we have taken quite a big step towards eliminating these problems. This blog post talk about what's changed and what this means for the user.
Prior to the Q2 2011 release the Telerik OpenAccess ORM product shipped, amongst the various assemblies, the 'Telerik.OpenAccess.Adonet2' assembly which had the ADO.NET specific implementation to obtain a connection,execute a command etc. This assembly linked against specific versions of all the various ADO.NET drivers. If the user upgraded to a newer version of the ADO.NET driver he needed to have an appropriate policy file in the GAC or a <bindingRedirect> entry that would redirect to the installed version of the driver.
With the Q2 2011 release, the standard .NET factory model approach is used to create the ADO.NET types and communicate with the data source. The entry point to the driver is the DbProviderFactories class that accepts the invariant name of a provider and resolves it to an instance of the appropriate DbProviderFactory. OpenAccess uses the invariant provider name specified in the connection string in the app.config or web.config file and if the provider name is not specified, the selected backend is used to calculate the invariant provider name.
Let’s look at an example. Suppose the following connection string that points to an Oracle XE database is specified in the app.config file
3: <add name="MyOracleData"
4: connectionString="data source=XE"
The provider name ‘Oracle.DataAccess.Client’ is supplied to the DbProviderFactories class in order to resolve it. The DbProviderFactories class uses the app.config/web.config and machine.config files to resolve the invariant name to the appropriate provider factory type. Usually, such an invariant provider name is already registered there, something similar to this -
4: <add name="Oracle Data Provider for .NET" invariant="Oracle.DataAccess.Client" description="Oracle Data Provider for .NET" type="Oracle.DataAccess.Client.OracleClientFactory,Oracle.DataAccess, Version=22.214.171.124, Culture=neutral,PublicKeyToken=89b483f429c47342" />
6: <!-- There can be many more drivers listed here. -->
7: <add name="SqlClient Data Provider" invariant="System.Data.SqlClient" description=".Net Framework Data Provider for SqlServer" type="System.Data.SqlClient.SqlClientFactory,System.Data, Version=126.96.36.199, Culture=neutral,PublicKeyToken=b77a5c561934e089" />
9: <add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory,System.Data.SqlServerCe, Version=188.8.131.52, Culture=neutral,PublicKeyToken=89845dcd8080cc91" />
The DbProviderFactories.GetFactory(String) method then returns the DbProviderFactory instance. This instance is used to create the ADO.NET types like a connection, parameter etc that OpenAccess needs to communicate with the database.
In cases where the app.config/web.config/machine.config do not provide information to resolve the invariant name that is used, OpenAccess provides a fallback mechanism that tries to load the the exact driver version that has been used to test the current version of the product. In effect, this means that the application behaves as if it would have been hard linked with the tested drivers i.e. the old behavior of OpenAccess prior to Q2 2011. This usage of the standard .Net driver loading mechanism allows for a much better control over which driver is to be used as the DbProviderFactory can be configured through the local app.config/web.config file.
For example: Let's say you have to make sure your application uses version a.b.c.d (where a.b.c.d is the desired assembly version number) of the Oracle driver. You can accomplish this with the following piece of configuration that needs to go to the your web.config or app.config file:
4: <remove invariant="Oracle.DataAccess.Client"/>
5: <add name="Oracle Data Provider for .NET"
7: description="Oracle Data Provider for .NET"
9: Oracle.DataAccess, Version=a.b.c.d, Culture=neutral,
10: PublicKeyToken=89b483f429c47342" />
The <remove> entry removes the potentially already existing mapping for ‘Oracle.DataAccess.Client’. The new provider factory type is then registered. Lastly you will need to make sure that the assembly with the right version number is loadable (deployed with your assemblies or through the GAC). The application will then use the specified version a.b.c.d of the Oracle driver.
Beginning with the Q2 2011 release, there is no longer the need to ship the Telerik.OpenAccess.Adonet2 assembly. All the relevant implementation has been moved to the Telerik.OpenAccess.Runtime assembly.