1

Background:

I have a .NET 4.5 application that uses Enterprise Library 6.0 to connect to an Oracle Database. In order to use the Oracle Data Provider for .NET, you have use EntLibContrib.Data.OdpNet.

I have a separate project and solution that contains the business and data access logic to connect to the database and returns domain objects.

Issue:

I went to use the assemblies in another project (in another solution) and ran into issues. I had added references to the following:

  • The .NET dlls produced by building the other solution
  • Microsoft.Practices.EnterpriseLibrary.Common
  • Microsoft.Practices.EnterpriseLibrary.Data
  • EntLibContrib.Data.OdpNet

After adding the appropriate settings to the configuration it should have worked as it has in other projects -- but when I tried to connect to the database, I received the following error:

The type 'EntLibContrib.Data.OdpNet.OracleDatabase, EntLibContrib.Data.OdpNet' cannot be resolved. Please verify the spelling is correct or that the full type name is provided.

I created a question for this error a while back. I never got a response, but the issue seem to "fix itself" when I added additional config information, but I never dug into what was causing the issue.

Since I ran into this issue again, I investigated and narrowed it that I need to have reference to an object that was part of EntLibContrib.Data.OdpNet. It also works if I have a reference an object that references references an object that is part of EntLibContrib.Data.OdpNet.

My solution was simply to do write a dummy variable in a class of my new project:

private static EntLibContrib.Data.OdpNet.OracleDataReaderWrapper dummyVarNotUsed; 

Even though dummyVarNotUsed is never used, simply having that line allows the EntLibContrib.Data.OdpNet assembly to be referenced correctly.

This is a hack, could someone shed some light on what is happening and how to better reference the dll?

Community
  • 1
  • 1
  • Might be pointing out the obvious but do you have your Using inserted correctly? – CathalMF Feb 17 '14 at 17:31
  • If you remove your dummy variable, clean/rebuild your solution, and then inspect the output directory, does EntLibContrib.Data.OdpNet appear there? – Sven Grosen Feb 17 '14 at 18:06
  • @CathalMF - yes was using "Using" correctly. But the thing is in the calling code doesn't call any methods EntLibContrib.Data.OdpNet assembly. The calls are made within the assemblies that the consumer calls. So I wouldn't normally need a using statement. –  Feb 17 '14 at 18:20
  • @ledbutter - yes, the EntLibContrib.Data.OdpNet does appear in the output directory after cleaning and rebuilding, and removing my dummy variable. That is the odd thing, it is there but it cannot be found unless there is a direct or indirect reference to one it's methods. –  Feb 17 '14 at 18:22

1 Answers1

1

Based off of this question, and the associated answer, I'd suggest trying to handle the AssemblyResolve event, so something like this:

//in your startup method
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

//...
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
    //not sure if this will be what the name is, you'd have to play with it
    if (args.Name == "EntLibContrib.Data.OdpNet.OracleDatabase")
    {
        return typeof(EntLibContrib.Data.OdpNet.OracleDataReaderWrapper).Assembly;
    }
    //not sure if this is best practice or not (to return null if truly unknown)
    return null;
}

That answer does suggest your current solution as the preferred method, but I agree that it does feel hacky. Not sure if this other method will feel any less hacky to you; it does to me in that at least this way you can clearly document this event handler instead of having a bogus variable somewhere with comments like //DON'T REMOVE, VERY IMPORTANT!!!

Community
  • 1
  • 1
Sven Grosen
  • 5,616
  • 3
  • 30
  • 52
  • thank you for finding the related question. The solution proposed doesn't have have the correct name (you can put in name == "x", just having the object reference "typeof(EntLibContrib.Data.OdpNet.OracleDataReaderWrapper).Assembly" in the method, loads the assembly. So it resolves problem even it is never called. The problem I see with this approach is the performance hit with using reflection and looping trying to match the assembly. –  Feb 17 '14 at 21:05
  • You are right about the performance hit, but if you really don't want to have that dummy variable around, this would be a workable alternative solution. – Sven Grosen Feb 17 '14 at 21:06