Multiple App.config files

Topics: Data Access Application Block, General discussion
Feb 5, 2007 at 3:36 PM
I'm purplexed by a situation and I'm wondering if anyone else has resolved this scenario.

I have 2 projects in my VS2005 solution. One is a Windows Application and the other is a Class Library. In the Windows Application project, I have referenced the EnterpriseLibrary.Common and EnterpriseLibrary.Data assemblies. I have also created the App.Config file and use it to store my DAAB settings via the Ent Lib console. Everything is working and I can retrieve data from my SQL Server 2005 Express database.

In my Class Library project, I'm storing my data access stuff. Right now it consists of 5 typed datasets. I noticed though, that when I created the data sources for these typed data sets, it generated an App.Config in the class library project and it stores Connection String information in it. This connection string info is used by the typed datasets.

Does anyone have any comments on how I should be consolidating these two App.Config files? Your thoughts would be appreciated.

Regards,
Roger Sutter
Feb 5, 2007 at 9:50 PM
You don't really need that app.config in the class library if you will be doing all your data access through Enterprise Library. The DataSet Wizard adds the connection strings in the class library's app.config if you tell it to, otherwise it puts them in the application settings.

My recommendation is to just ignore the app.config in the class library and just not deploy it with the application. It isn't necessary for deployment. You could delete it, but VS might complain at you in the designer as well as start storing new connection strings in the application settings as you maintain the application.

Regards,

Dave

____________________

David Hayden
Microsoft MVP C#
Feb 5, 2007 at 10:37 PM
Dave,

I am not sure what you mean by "...doing all your data access through the Enterprise Library." Take the following two lines of code:

Database db = DatabaseFactory.CreateDatabase("PortalDatabase");

CustomersDS customerDataSet = new CustomersDS();

Based on Roger's case I assume the first line will make use of the Windows Application app.config file, but the second line will use the app.config file from his class library. How do you force the DataSet code to not use the Wizard-based connection string and do it through the Enterprise Library?

Regards,

Rich
Feb 21, 2007 at 4:02 PM
Edited Feb 21, 2007 at 5:17 PM
I've got a similar problem that I'm hoping someone has some insight on.

.NET 2.0, 1 solution, 2 projects (1 win client, 1 class library). I'm using the DAAB as my interface to the database. The class library is the data access layer w/ references to the DAAB. I have an app.config in the class libray project and an app.config in the win client project. The class library cannot find the information to handle the factory.createdatabase() statement unless I put the ELIB config stuff into the app.config for the win client project.

I know that in the old 1.1 stuff, you could only have 1 app.config, right?

But in 2.0, I thought that each piece of your application, EXE, DLL, etc. would use it's own app.config and if you needed global config stuff across all components you had to add something to an external/global common.config file and put an appSettings section in there, and put something in the app.config to make it look there as well.

Anyway...anybody know how to allow my DLL to have it's own app.config and not look at the client. My goal here is a generic data access library w/ wrappers around some of the DAAB stuff to simplify it. But I want the app.config at the DLL level to reuse it across applications and not have the app itself need to know or supply anything about the database connection.

Any ideas ?

EDIT: Been exploring some of David Haden's (who posted above) blog items and I'm heading down a path w/ the whole IConfigurationSource and FileConfiguration source (creating a data.config). But, when I load it, it seems to be looking for the data.config in my main application path, not in the directory where the DLL/class library code is.

Thanks in advance,
Chris
Feb 21, 2007 at 5:50 PM
Chris - take a look at this post for some options.

Tom
Feb 21, 2007 at 6:12 PM
Edited Feb 21, 2007 at 6:14 PM
Tnanks, actually it was a combination of your blog stuff you linked to and the stuff on David Haden's blog...I used both to get me to the point of loading a file, which it working great...

Only issue I can't seem to figure out is why my DLL is still looking in the EXE bin/debug location for the file I created. The startup app seems to be driving where it looks.

I want the class library to load data.config from the source code location, and eventually the path where the DLL resides. I can hardcode the entire path in my class library, in the code...but that's not going to work once the DLL is deployed.

Dim source As IConfigurationSource = _
New FileConfigurationSource("C:\data.config")

But, what I want is to load from whereever the class is running from, it's application path. Is there a way to make it do that, or am I going to have to 'discover' the location of the DLL inside it's own Sub New w/ reflection and get the path that way?

Chris
Feb 21, 2007 at 8:07 PM
Chris,

Unless your assembly is being loaded into a separate AppDomain from the main application, it's application path and the application path of the main application are the same. Your assembly gets loaded into the AppDomain of the main application and does not run in its own AppDomain. Hence DAAB code within the assembly will always look for a configuration file in the main application directory unless you tell it otherwise.

You are on the right track. You are using a FileConfigurationSource that will allow you to specify an absolute or relative path to a configuration file to get the configuration settings.

If you have a directory off the main application directory, called Configuration, where you want to store all the configuration files, you can specify that the DAAB use a Data.config file in that directory as such...

IConfigurationSource source = new FileConfigurationSource("Configuration/Data.Config");
DatabaseProviderFactory factory = new DatabaseProviderFactory(source);
database = factory.CreateDefault();

Note that the code is specifying a relative path and not an absolute path.

If you want to pull the config file from the bin directory where your assemblies are normally kept, you could do:

IConfigurationSource source = new FileConfigurationSource("bin/Data.Config");
DatabaseProviderFactory factory = new DatabaseProviderFactory(source);
database = factory.CreateDefault();

I hope this helps.

Regards,

Dave

________________________

David Hayden
Microsoft MVP C#
Feb 21, 2007 at 8:24 PM
Edited Feb 21, 2007 at 8:25 PM
Thanks, this all helps alot, the configuration stuff is SO different than .NET 1.1 and in prior 2.0 apps, just didn't have a need for all this. A single app.config has always worked for what I was trying to do. Couple that w/ the fact that this is my first exposure to DAAP and app blocks in general, boy and I'm in a learning curve right now.

Anyway, what I did figure out was that my data.config wasn't making into my bin/debug and bin/release folder. Once I changed the property of it to 'copy always' and set it to 'content', now it copies down and works great.

I'm now able to do the following, from w/in the DLL itself.

Dim path As String = _
System.AppDomain.CurrentDomain.BaseDirectory & "data.config"

Dim source As IConfigurationSource = _
New FileConfigurationSource(path)

Dim factory As DatabaseProviderFactory = _
New DatabaseProviderFactory(source)

_db = factory.Create("Default")


I definitely like the FileConfigurationSource stuff, it's going to make my design and deployment much more robust.

Chris
Jul 21, 2009 at 8:14 PM
Edited Jul 22, 2009 at 5:52 PM

I've read the documentation and Tom's blog, but I still cannot seem to get my externally configured connectionstrings section to be loaded.  Any advice?  FYI: Version 4.0 of the Enterprise Library. 

Code:

ConnectionStringSettings settings = ConfigurationManager.ConnectionStrings["default"];  
if (settings == null || settings.ConnectionString.Trim() == "")
throw new ConfigurationErrorsException("No default connection string.");

Error:

System.Configuration.ConfigurationErrorsException: No default connection string.

Web.config:

 <configuration>  
<configSections>
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</configSections>
<enterpriseLibrary.ConfigurationSource selectedSource="File Configuration Source">
<sources>
<add name="File Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
filePath="demo.config" />
</sources>
</enterpriseLibrary.ConfigurationSource>
</configuration>

demo.config:

<?xml version="1.0"?>  
<configuration>
<connectionStrings>
<clear/>
<add name="default" connectionString="User Id=etc., etc."/>
</connectionStrings>
</configuration>

 

Jul 22, 2009 at 9:10 PM
Edited Jul 22, 2009 at 9:20 PM

Answering my own question...Configuration settings in an Enterprise Library ConfigurationSource are not accessible via ConfigurationManager.

The best solution here is to use configSource attribute of the individual config sections as Tom points out in his blog:

<connectionStrings configSource="demo.config" />

where demo.config includes only the configuration element of interest:

<connectionStrings>
    <add name="Tom's Connection" connectionString="Database=EntLibQuickStarts;Server=(local)\SQLEXPRESS;Integrated Security=SSPI;"
        providerName="System.Data.SqlClient" />
</connectionStrings>

Tom Hollander's reply: "The reason this isn't working is because <connectionStrings> is a standard .NET configuration section, not an Enterprise Library one. The .NET configuration APIs know nothing about ConfigurationSources etc. It's been ages since I looked at this, but IIRC it's still possible to initialise a Database object using a custom configuration source to achieve what you're looking for, but the ConfigurationManager.ConnectionStrings property is never going to know about the external file."

Thanks, Tom.

Jul 23, 2009 at 1:41 AM

Yes, the ConfigurationManager class doesn't know about the IConfigurationSource object which is an Entlib class.  What would work is if you call DatabaseFactory.CreateDatabase().  The resulting Database object would contain the connection string since the CreateDatabase method without parameter would look for the default connection string.

 

Sarah Urmeneta
Global Technology and Solutions
Avanade, Inc.
entlib.support@avanade.com