DAAB on webserver w/ custom data provider ???

Topics: Data Access Application Block
Aug 7, 2008 at 3:57 AM
Edited Aug 7, 2008 at 4:03 AM
Hoping one of you guys can help here...I've got an issue deploying the DAAB to a 2k3 server box, but it's definitely config related due to something goofy I'm doing.  I've got a custom data provider class (inherits from generic database) that is contained w/in a data layer dll w/in my web app.  So it's just another class inside my project.  I'm using it to simply get param discovery using ODP.Net while still using all the other stuff in the generic database.

There is an error being generated when attempting to browse to the website.  This all works fine in development, and even on my local XP SP2 IIS webserver.  But, when I copy everything out to my 2k3 webserver, I get the error below.

I'm guessing it's something to do w/ the provider class I've created (OracleOdpDatabase) not being in the GAC ... but I don't understand why it works on my local IIS and not on the remote.

The error and provider code in my class below that.  There is also a provider mapping entry in my web.config that maps OracleOdpDatabase to Oracle.DataAccess.Client to get the mapping to ODP.Net.

Any ideas would be greatly appreciated...
Chris



[ConfigurationErrorsException: Failed to find or load the registered .Net Framework Data Provider.]
   System.Data.Common.DbProviderFactories.GetFactory(DataRow providerRow) +547
   System.Data.Common.DbProviderFactories.GetFactory(String providerInvariantName) +194
   HighlightEditor.Data.OracleOdpDatabaseAssembler.Assemble(String name, ConnectionStringSettings connectionStringSettings, IConfigurationSource

configurationSource) in C:\Projects\HighlightEditor\HighlightEditor.Data\DbHelper.vb:617
   Microsoft.Practices.EnterpriseLibrary.Data.DatabaseCustomFactory.CreateObject(IBuilderContext context, String name, IConfigurationSource

configurationSource, ConfigurationReflectionCache reflectionCache) +283


#Region "Oracle.DataAccess.Client (ODP.Net) Provider Mapping Classes"

<DatabaseAssembler(GetType(OracleOdpDatabaseAssembler))> _
Public Class OracleOdpDatabase
  Inherits GenericDatabase

  Public Sub New(ByVal connectionString As String, ByVal dbProviderFactory As DbProviderFactory)
    MyBase.New(connectionString, dbProviderFactory)
  End Sub 

  Protected Overrides Sub DeriveParameters(ByVal discoveryCommand As DbCommand)
    OracleCommandBuilder.DeriveParameters(
    CType(discoveryCommand, OracleCommand))
  End Sub

End Class
 
Public Class OracleOdpDatabaseAssembler
Implements IDatabaseAssembler
  Public Function Assemble(ByVal name As String, ByVal connectionStringSettings As ConnectionStringSettings, ByVal configurationSource As IConfigurationSource) As Database Implements IDatabaseAssembler.Assemble
    Dim providerFactory As DbProviderFactory = DbProviderFactories.GetFactory(connectionStringSettings.ProviderName)
    Return New OracleOdpDatabase(connectionStringSettings.ConnectionString, providerFactory)
  End Function

End Class

#End Region

Aug 7, 2008 at 5:52 PM

Hi,

The error is caused by a missing entry for "Oracle.DataAccess.Client" in the DbProviderFactories element of your configuration; this entry was very likely added in your dev box when you installed ODP, but you need it in your server. This entry can be specified in your app's web.config file (but you need to do it manually, there's no tool support for that) or in your server's machine.config file. You don't need to GAC your class, but if you add the provider entry to the machine.config file you need to make sure the ODP assembly is in the GAC.

EntLib relies on the providers infrastructure from ADO.NET 2.0, so you need to make sure all providers referenced by connection strings used with EntLib are properly registered.

Hope this helps,
Fernando

Aug 7, 2008 at 5:58 PM
Fernando,

Thanks, I'll check that link out.  So I can do this in my app.config w/o messing w/ the machine.config?

My preference is to handle this w/in the app/site itself and not have to mess w/ the higher level IIS configuration, GAC or anything else.

Am I understanding this correctly?
Aug 7, 2008 at 6:12 PM
Hi,

Yes, you're on the right track. Although the link I sent you only mentions the machine.config, you can add the provider entries to your app's config file (just like you can with any configuration setting that is not locked.)

Fernando
Aug 7, 2008 at 6:35 PM
Starting to make some sense, but no luck w/ going that route.  I compared my machine.config files between development pc and web server and the only difference w/ regard to Oracle.DataAccess.Client is that the server has the 64-bit version number, but the token is the same.  I made the change to my web.config to add the system.data dbproviderfactory entry for this and got a different error (value 'Oracle.DataAccesss.Client' is already present'), which makes sense because ODP.Net is already installed on the server and there is an existing entry in the machine.config.  So, took that out of my web.config and now I'm back to confused.

development machine.config file
            <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=2.102.2.20, Culture=neutral, PublicKeyToken=89b483f429c47342" />

server machine.config file
            <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=2.102.3.2, Culture=neutral, PublicKeyToken=89b483f429c47342" />

At this point, not sure where to go next.  If ODP.Net is installed on the server, Ent Lib installed on the server, copies of all DLLs of these 2 things in my site BIN folder...all the entries in machine.config look like they are there and I have my provider mapping (which works in development) in the web.config...what else could it be?

Do I need to segment off my OracleOdpDatabase classes into a seperate DLL and create entries for those in machine.config (or web.config) like Oracle.DataAccess.Client has?

Aug 7, 2008 at 6:56 PM

If the entry is there, then it has to be a load problem. I'd check with the fusion log viewer (if possible) and try to determine if the ConfigurationErrorsException has an inner exception with useful information.

I tried to repro with a console app and I could only get the exact error message you're getting by specifying a entry with an invalid type name on a valid assembly. I'm not sure why you're getting this; you may want to try by trying to resolve Type.GetType("Oracle.DataAccess.Client.OracleClientFactory, Oracle.DataAccess, Version=2.102.3.2, Culture=neutral, PublicKeyToken=89b483f429c47342", true) and see what the problem is. If you can load it, then there's probably an issue when a new instance is created.

I suggest you try to diagnose this with an application that doesn't use EntLib; just try to get the Oracle provider doing DbProviderFactories.GetFactory("Oracle.DataAccess.Client").

Fernando

Aug 7, 2008 at 6:59 PM
For grins, I just did the following...removed my provider mapping to stop using my inherited class and set the connection to use System.Data.OracleClient and (as expected) it worked on my development machine but failed on the server.  However, this time I got a TNS 12415 error on the server instead of the other errors above.

So...starting to think the ODP.Net installation on the server is suspect.  I need to dig further.  This box has only been used for SSRS stuff and has not yet had any other websites deployed on it...so maybe ODP.Net never worked correctly at all.

I'm about to throw in the towel...

 <dataConfiguration defaultDatabase="MyDatabase">
  <!--<providerMappings>
   <add databaseType="MyProject.Data.OracleOdpDatabase, MyProject.Data, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" name="Oracle.DataAccess.Client"/>
  </providerMappings>-->
 </dataConfiguration>
 <connectionStrings>
  <add name="MyDatabase" connectionString="Data Source=MyServer;Persist Security Info=True;User ID=MyUser;Password=MyPassword;" providerName="System.Data.OracleClient"/>
 </connectionStrings>
Aug 7, 2008 at 7:03 PM

I suggest you try to diagnose this with an application that doesn't use EntLib; just try to get the Oracle provider doing DbProviderFactories.GetFactory("Oracle.DataAccess.Client").


funny, as you wrote that had already started building an app with that exact test...from your earlier link...

you have been massively helpful, can't thank you enough.  i'm suspect of the oracle install at this point.  your comments are at least getting me to think about what else might be wrong.  i was so deep down the wrong path i didn't think to try the simple stuff.