DAAB: How to reload database type registrations when connection string settings change in the config file at runtime

Topics: Data Access Application Block
Apr 18, 2011 at 9:55 PM

DAAB: How to reload database type registrations when connection string settings change in the config file at runtime?

We have a situation where the connection strings settings are updated during runtime. So, we want to reload the config file to re-register database type registrations to use the updated connection strings. Just refreshing the config file section for connection strings is not causing the DAAB to reload database type registrations. Is there a way to force DAAB to re-load type registrations?

 

Thank you,

Ramesh

Apr 18, 2011 at 10:24 PM
Edited Apr 18, 2011 at 10:24 PM

Resetting the default container to null forces a relod but wondering if there is a more direct & efficient way to force re-load type registrations.

 

EnterpriseLibraryContainer.Current = null;

 

Apr 19, 2011 at 1:37 AM

You can do this:

EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);

where configSource is an instance of IConfigurationSource.  This same code is what is also shown in the sample codes for the Fluent Configuration API.

 

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

Apr 19, 2011 at 2:05 AM
Edited Apr 19, 2011 at 2:10 AM

If we replace the current container by creating a new default container as mentioned in your post would the new container have registrations from all other application blocks that are configured through the application configuration such as caching etc.? What happens to the instances of objects that have already been created in other application blocks? For example:

  1. Application uses caching
  2. Application uses data access
  3. Caching is configured through application configuration file
  4. On application startup, the caching application block registrations are loaded from the config file
  5. A cache manager instance is created on application’s request
  6. Data access is configured using fluent configuration API - EnterpriseLibraryContainer.Current is replaced with a new default container that has the new configuration for data access

So, at this point:

  1. Does the new container created retain config from all other application blocks?
  2. Is the cache manager instance created prior to replacing the current container still valid?

 Thank you,

Ramesh

Apr 19, 2011 at 7:22 AM
Edited Apr 19, 2011 at 7:22 AM

Yes, the other existing configuration sections are retained.  The only one which gets replaced is the one which you configured using the Fluent Configuration API.  Thus, your previously created cache manager instance is still valid. 

 

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

Apr 19, 2011 at 6:39 PM

Thank you Sarah.

Thank you,

Ramesh

Apr 20, 2011 at 11:21 PM

Hello Sarah,

After starting to use the Fluent Configuration API to configure DAAB it seems like the registrations for the Caching Application Block are being wiped out and call to retrieve a cache manager results in the following error:

Microsoft.Practices.ServiceLocation.ActivationException was unhandled by user code

Message=Activation error occured while trying to get instance of type ICacheManager, key ""

Source=Microsoft.Practices.ServiceLocation

StackTrace:

at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 53

at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance[TService](String key) in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 103

at Microsoft.Practices.EnterpriseLibrary.Caching.CacheFactory.InnerGetCacheManager(String cacheManagerName) in e:\Builds\EntLib\Latest\Source\Blocks\Caching\Src\Caching\CacheFactory.cs:line 66

at Microsoft.Practices.EnterpriseLibrary.Caching.CacheFactory.GetCacheManager() in e:\Builds\EntLib\Latest\Source\Blocks\Caching\Src\Caching\CacheFactory.cs:line 37

at Camstar.Data.SiteConfig.GetValue(String name, String defaultValue) in C:\InSite\Development\Servers.NET\Camstar.Data\SiteConfig.cs:line 27

at Camstar.Security.RBAC.Services.AuthenticationService..ctor() in C:\InSite\Development\Servers.NET\Camstar.Security.RBACServices\AuthenticationService.cs:line 20

at CamstarSecurityServerUnitTest.AuthenticationServiceTest.AuthenticateImpersonatorTest() in C:\InSite\Development\Servers.NET\CamstarSecurityServer\CamstarSecurityServerUnitTest\AuthenticationServiceTest.cs:line 97

InnerException: Microsoft.Practices.Unity.ResolutionFailedException

Message=Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager", name = "(none)".

Exception occurred while: while resolving.

Exception is: InvalidOperationException - The current type, Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, is an interface and cannot be constructed. Are you missing a type mapping?

-----------------------------------------------

At the time of the exception, the container was:

Resolving Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager,(none)

Source=Microsoft.Practices.Unity

TypeRequested=ICacheManager

StackTrace:

at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:line 515

at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:line 485

at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:line 173

at Microsoft.Practices.Unity.UnityServiceLocator.DoGetInstance(Type serviceType, String key) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityServiceLocator.cs:line 64

at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 49

InnerException: System.InvalidOperationException

Message=The current type, Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, is an interface and cannot be constructed. Are you missing a type mapping?

Source=Microsoft.Practices.Unity

StackTrace:

at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructInterface(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs:line 209

at BuildUp_Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager(IBuilderContext )

at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\DynamicMethodBuildPlan.cs:line 37

at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\BuildPlanStrategy.cs:line 43

at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\StrategyChain.cs:line 110

at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\UnityContainer.cs:line 511

InnerException:

I verified that configuring DAAB using fluent API is causing this issue by having a call to retrieve cache manager before and after the DAAB configuration through Fluent API. The ‘before’ call succeeds but the ‘after’ call fails with above exception. The code using Fluent API to configure DAAB is something like this:

public void ConfigureDAAB()

{

var configBuilder = new ConfigurationSourceBuilder();

configBuilder.ConfigureData()

.ForDatabaseNamed("School")

.ThatIs

.ASqlDatabase()

.WithConnectionString(ConnectionString)

.AsDefault();

var configSource = new DictionaryConfigurationSource();

configBuilder.UpdateConfigurationWithReplace(configSource);

EnterpriseLibraryContainer.Current =

EnterpriseLibraryContainer.CreateDefaultContainer(configSource);

}

The application config file contains the configuration for Caching Application Block with a couple of cache managers defined. Is there a way only to override the DAAB configuration using fluent API not affecting the other application blocks configured through the config file?

Thank you,

Ramesh

704 973 6975

From: AvanadeSupport [email removed]
Sent: Monday, April 18, 2011 11:22 PM
To: Ramesh Nagamalli
Subject: Re: DAAB: How to reload database type registrations when connection string settings change in the con... [entlib:254400]

From: AvanadeSupport

Yes, the other existing configuration sections are retained. The only one which gets replaced is the one which you configured using the Fluent Configuration API. Thus, your previously created cache manager instance will be retained.

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

Apr 21, 2011 at 12:48 AM
Edited Apr 21, 2011 at 3:43 AM

Update to the above code to use 'SystemConfigurationSource' instead of the 'DictionaryConfigurationSource' results in the following error:

Cannot add a ConfigurationSection with the same name that already exists.

 Updated code snippet:

           var configSourceBuilder = new ConfigurationSourceBuilder();

           var configBuilder = configSourceBuilder.ConfigureData();

            ...

           var configSource = new SystemConfigurationSource();

           configSourceBuilder.UpdateConfigurationWithReplace(configSource);

           EnterpriseLibraryContainer.Current = EnterpriseLibraryContainer.CreateDefaultContainer(configSource);

Apr 21, 2011 at 1:17 AM

Sorry for multiple posts on this issue but thought that this information will be helpful in understanding the problem and getting a resolution for it.

On stepping into the EntLib source code, the above mentioned error occurs when adding the 'connectionStrings' section from the ConfigurationSourceBuilder instance to the SystemConfigurationSource instance that already has the 'connectionStrings' section with one entry 'LocalSQLServer' that comes from the machine config file.

So, using SystemConfigurationSource is not the right way to replace the DAAB configuration section by using Fluent Configuration API at runtime? What is the correct solution for this issue?



Thank you,

Ramesh

Apr 24, 2011 at 3:44 PM

I'm afraid that is the behaviour of the FluentConfiguration UpdateConfigurationWithReplace it recreates the entire configuration file.

Anyway, try and check the following related post and hope it may provide you an idea how you will be able to accomplish your scenario

http://entlib.codeplex.com/discussions/253733

http://entlib.codeplex.com/discussions/247686

Hope this helps

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

Apr 25, 2011 at 12:18 AM

I understand that the Fluent Configuration API UpdateConfigurationWithReplace replaces the existing config sections with those that are built using that object (ConfigurationSourceBuilder). But the problem is that when SystemConfigurationSource instance is used as a parameter for this function it does not replace an existing section but results in an error as mentioned earlier.

Cannot add a ConfigurationSection with the same name that already exists.

Thank you,

Ramesh

From: AvanadeSupport [email removed]
Sent: Sunday, April 24, 2011 7:45 AM
To: Ramesh Nagamalli
Subject: Re: DAAB: How to reload database type registrations when connection string settings change in the con... [entlib:254400]

From: AvanadeSupport

I'm afraid that is the behaviour of the FluentConfiguration UpdateConfigurationWithReplace it recreates the entire configuration file.

Anyway, try and check the following related post and hope it may provide you an idea how you will be able to accomplish your scenario

http://entlib.codeplex.com/discussions/253733

http://entlib.codeplex.com/discussions/247686

Hope this helps

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 25, 2011 at 3:44 AM

I saw a similar post here. I guess this is not something caused by Enterprise Library. It seems you cannot replace the connectionstring section without using a different configuration source.

 

 

Noel Angelo Bolasoc
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

Apr 25, 2011 at 7:19 PM

The FluentConfiguration API UpdateConfigurationWithReplace attempts to remove the connection strings section before trying to add from the confuguration builder but it seems like the remove does not actually remove the connection strings coming from the machine config file. I think that this API should treat the connection strings section specially as identified in the article mentioned above and handle the addition of connection strings configured programmatically through the builder.

Thank you,

Ramesh

Apr 25, 2011 at 7:25 PM

Logged following issue for this behavior: http://entlib.codeplex.com/workitem/30586