redsoxfantom
redsoxfantom

Reputation: 956

Referencing the correct version of Oracle.DataAccess in .NET

I'm trying to reference Oracle.DataAccess from a .NET 4.0 project, written on Visual Studio 2013. My machine's GAC has two versions of Oracle.DataAccess installed: 4.112.1.2 (provided by Oracle version 11gr2) and 4.121.2.0 (provided by Oracle version 12c).

I want to reference version 4.112.1.2 (my project must run with %ORACLE_HOME% set to 11gr2's install location, and referencing 4.121.2.0 causes runtime failures when this is the case). I do not have an admin account on my machine, so I can't just uninstall the 12c dll.

I have tried the following steps to force the executable to load the 4.112.1.2 dll at runtime:

  1. Reference the dll in my .csproj file using the strong name:

    <Reference Include="Oracle.DataAccess, Version=4.112.1.2, Culture=neutral, PublicKeyToken=89b483f429c47342, processorArchitecture=x86"/>

  2. Updating my App.Config file to force a redirect:

<dependentAssembly>
    <assemblyIdentity name="Oracle.DataAccess" publicKeyToken="89b483f429c47342" culture="neutral"/>
    <codeBase version="4.112.1.2" href="C:\Path\To\11gr2\Oracle.DataAccess.dll"/>
    <bindingRedirect oldVersion="4.121.2.0" newVersion="4.112.1.2"/>
    <publisherPolicy apply="no"/>
</dependentAssembly>

  1. I modified my PATH to make the 11gr2 Client's bin directory first on my path:

    set PATH="C:\path\to\11gr2\BIN;%PATH%"

No matter what I do, however, the executable loads the 4.121.2.0 dll from the GAC at runtime. Here's what it says when I attach a debugger:

'MyApp.exe' (Managed (4.0.30319)): Loaded 'C:\WINDOWS\Microsoft.Net\assembly\GAC_32\Oracle.DataAccess\v4.0_4.121.2.0_89b483f429c47342\Oracle.DataAccess.dll'

I've read through Microsoft's documentation on assembly binding (here and here). I've also read the StackOverflow answers that seem to be related to my issue (here and here), but nothing has worked.

How do I force .NET to load the correct DLL version at runtime from the GAC?

EDIT:

Wernfried's answer leads me to think I may be looking at this the wrong way. Here's exactly what's happening:

I run my application with ORACLE_HOME=C:\ORACLE\ora12c, everything works as normal (database accesses succeed, application is happy)

I run my application with ORACLE_HOME=C:\ORACLE\ora11gr2 (the required version). Application crashes with following exception:

Oracle.DataAccess.Client.OracleException ORA-12557: TNS:protocol adapter not loadable.
<stacktrace follows>

Following the stacktrace, I discovered that the error occurred in the call my application made to create a database connection. I've checked my connection string and verified that it is correct (and that it is the same connection string that was succeeding with 12c). I then discovered that version of the Oracle.DataAccess dll I was calling was the 12c one, not the 11gr2 one. From this, I concluded that I needed to modify the call to load the dll to "force" the 11gr2 one. If I'm barking up the wrong tree, please let me know!

Upvotes: 0

Views: 10281

Answers (2)

redsoxfantom
redsoxfantom

Reputation: 956

I believe I have it fixed.

What got it working for me was to unset the ORACLE_HOME environment variable, and to put C:\Path\to\11gr2\bin at the beginning of my path, like so:

set PATH=C:\Path\to\11gr2\bin;%PATH%

Upvotes: 0

Wernfried Domscheit
Wernfried Domscheit

Reputation: 59456

As far as I know, ODP.NET provider 4.112.1.2 works only with Oracle Client 11.2, resp. ODP.NET provider 4.121.2.0 requires Oracle 12.1 Client.

Do you have both versions of Oracle Client installed on your machine?

In order to use one or the other you must also set your PATH environment variable accordingly. PATH must include folder of Oracle client binaries you like to use in your application.

Note, the architectures (i.e. 32-bit vs. 64-bit) have to be all the same at your application, the Oracle Client and the ODP.NET provider.

But why do you like to force a particular version of ODP.NET? I recommend to use this reference

<Reference Include="Oracle.DataAccess">
  <SpecificVersion>False</SpecificVersion>
  <Private>False</Private>
</Reference>

then your application will load automatically the correct version of ODP.NET no matter what is installed on your machine (or the machine of your customer).

Anyway, in case you like to run test and force particular version of ODP.NET you can use dynamic binding. For this your code like this:

using (OracleConnection con = new OracleConnection(connString))
{
    con.Open();
    ...
}

has to be re-written like this one:

var DLL = default(Assembly);
DLL = Assembly.LoadFrom(@"C:\Path\To\11gr2\Oracle.DataAccess.dll");
// resp for GAC:
// DLL = Assembly.Load(String.Format("Oracle.DataAccess, Version={0}.{1}.*.*, Culture=neutral, PublicKeyToken=89b483f429c47342", 1, 112));    
var type = DLL.GetType("Oracle.DataAccess.Client.OracleConnection", true, false);
using ( dynamic con = Activator.CreateInstance(type, connString) ) {
    con.Open();
    ...
 }

Upvotes: 1

Related Questions