How Does Telerik® Data Access Resolve the ADO.NET Driver

This article is relevant to entity models that utilize the deprecated Visual Studio integration of Telerik Data Access. The current documentation of the Data Access framework is available here.

Prior the Q2 2011 release of Telerik Data Access, the Telerik.OpenAccess.Adonet2.dll assembly was part of the product. That assembly had the ADO.NET specific implementation to obtain a connection, execute a command, etc. This assembly was linked against specific versions of all the various ADO.NET drivers. If the user needed to upgrade to a newer version of the ADO.NET driver, he had to have an appropriate policy file in the GAC or a bindingRedirect entry that would redirect to the installed version of the driver.

Beginning with the Q2 2011 release, there are no direct hard links to the needed database drivers in the product. The standard .NET way of loading ADO drivers is used. The DbProviderFactories class is used to resolve an user given, invariant name to a DbProviderFactory instance.

The invariant provider name is either calculated from the specified backend (Telerik.OpenAccess.Config.Sql.BackendEnumeration) or taken from the providerName attribute of the connection string entry in the app.config or web.config file.

Suppose, you have a connection string that points to an Oracle XE database.

<configuration>
<connectionStrings>
 <add name="MyOracleData"
      connectionString="data source=XE"
      providerName="Oracle.DataAccess.Client"/>
 </connectionStrings>
</configuration>

The providerName (Oracle.DataAccess.Client) is passed to the DbProviderFactories class in order to resolve it. The DbProviderFactories class uses the app(web).config and machine.config files to resolve the invariant name to the appropriate provider factory type. The machine.config file is located in x:\<windows>\Microsoft.NET\Framework\<version>\config\machine.config.

Usually, such an invariant provider name is already registered in the machine.config:

<?xml version="1.0"?>
<configuration>
 <configSections>    
 <system.data>
   <DbProviderFactories>

     <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=4.112.2.0, Culture=neutral, PublicKeyToken=89b483f429c47342" />

     <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=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />

     <add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" 
          description=".Net Framework Data Provider for MySQL" 
          type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.3.6.0,
                Culture=neutral, PublicKeyToken=c5687fc88969c44d" />

     <add name="SQLite Data Provider" invariant="System.Data.SQLite" 
          description=".Net Framework Data Provider for SQLite" 
          type="System.Data.SQLite.SQLiteFactory, System.Data.SQLite, Version=1.0.66.0, 
                Culture=neutral, PublicKeyToken=db937bc2d44ff139" />

   </DbProviderFactories>
 </system.data>
</configuration>

The DbProviderFactories.GetFactory(String) method then returns the DbProviderFactory instance. This instance is used to create the ADO.NET types that Telerik Data Access needs to communicate with the database (like connection, command, parameter, etc).

In cases where the machine.config file does not provide information to resolve the invariant name, Telerik Data Access provides a fallback mechanism that tries to load the exact driver version that has been used to test the current version of the product. In this case, the application behaves as if it would have been hard linked with the tested drivers, i.e. the old behavior of Telerik Data Access.

This usage of the standard .NET driver loading mechanism allows a much better control over which driver is to be used. The DbProviderFactory can be configured through the application app.config/web.config file. It is no longer needed to remap the driver assembly using a .policy file when a different version should be used.

Suppose, you need to use the a.b.c.d version of the Oracle driver in your application. You can accomplish this with the following piece of configuration that needs to be placed in the app(web).config file of the application.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <configuration>
   <system.data>

     <DbProviderFactories>
       <remove invariant="Oracle.DataAccess.Client"/>
       <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=a.b.c.d, Culture=neutral,PublicKeyToken=89b483f429c47342" />
     </DbProviderFactories>

   </system.data>
 </configuration>
</configuration>

The <remove> entry removes the potentially existing mapping for Oracle.DataAccess.Client. The new provider factory type is then registered. Finally, you need to ensure that the assembly with the right version number is loadable (deployed with your assemblies or installed in the GAC). The application will then use the specified version a.b.c.d of the Oracle driver.