Old chestnut! The type Database cannot be constructed. You must configure the container to supply this value

Topics: Data Access Application Block
Feb 22, 2012 at 12:22 PM
Edited Feb 22, 2012 at 12:23 PM

Hi,

I have seen loads of posts for this, but none of the solutions works for me. I have spent hours trying to get this to work, using ever smaller and smaller code to try to work out what is going on!

I now have a console app which simply runs the following code:

 Database db = EnterpriseLibraryContainer.Current.GetInstance<Database>("QueueDatabase");

 

and the config is:

<?xml version="1.0"?>
<configuration>
  <configSections>
    <!--<section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />-->
    <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>
 
  <dataConfiguration defaultDatabase="QueueDatabase">
    <providerMappings>
      <add databaseType="Microsoft.Practices.SmartClient.EnterpriseLibrary.SmartClientDatabase, Microsoft.Practices.SmartClient.EnterpriseLibrary"
        name="System.Data.SqlServerCe.3.5" />
    </providerMappings>
  </dataConfiguration>
  <connectionStrings>
    <add name="QueueDatabase" connectionString="DataSource=Database1.sdf"
      providerName="System.Data.SqlServerCe.3.5" />
  </connectionStrings>
</configuration>

and I get the following error:

Microsoft.Practices.ServiceLocation.ActivationException was caught
  Message=Activation error occured while trying to get instance of type Database, key "QueueDatabase"
  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 ConsoleApplication1.Program.Main(String[] args) in C:\Program Files (x86)\Microsoft Patterns & Practices\Smart Client Software Factory 2010\Source\QuickStarts\Offline\ConsoleApplication1\Program.cs:line 23
  InnerException: Microsoft.Practices.Unity.ResolutionFailedException
       Message=Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Data.Database", name = "QueueDatabase".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type Database cannot be constructed. You must configure the container to supply this value.
-----------------------------------------------
At the time of the exception, the container was:

  Resolving Microsoft.Practices.EnterpriseLibrary.Data.Database,QueueDatabase

       Source=Microsoft.Practices.Unity
       NameRequested=QueueDatabase
       TypeRequested=Database
       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 type Database cannot be constructed. You must configure the container to supply this value.
            Source=Microsoft.Practices.Unity
            StackTrace:
                 at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs:line 289
                 at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\Creation\DynamicMethodConstructorStrategy.cs:line 71
                 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.ObjectBuilder2.DynamicMethodBuildPlanCreatorPolicy.CreatePlan(IBuilderContext context, NamedTypeBuildKey buildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\DynamicMethodBuildPlanCreatorPolicy.cs:line 48
                 at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\BuildPlanStrategy.cs:line 37
                 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:

 

This is driving me mad. In the same VS 2010 solution I have the original Quickstart 'Quickstarts.DisconnectedAgent' running exactly the same line of code and using the same references - and it works. I just cannot get this working in any other project.

 

Please help. Thanks.

Chris

Feb 23, 2012 at 6:23 AM

Usually that error is because of a configuration issue.  Can you verify that the configuration file (i.e. consoleapp.exe.config) in the bin\(debug|release) folder contains the appropriate configuration?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Feb 23, 2012 at 9:11 AM
Edited Feb 23, 2012 at 3:58 PM

HI Randy - yes, I can confirm that the config file is identical to the app.config in the source folder.

I have been paring down the code to virtually nothing - now just a single line as I said, and have checked the dll's deployed in the runtime folder to those that are in the runtime folder for the 'Quickstarts.DisconnectedAgent' WinForms app that does work - and everything is identical. I find this completely inexplicable - not to say extremely frustrating.

If I examine the registrations in the 'EnterpriseLibraryContainer.Current' instance I can see in the correctly functioning project that the 'QueueDatabase' Sql Server Ce instance has been resolved and loaded as follows (from Quickwatch results window):

-        [4]    {Microsoft.Practices.Unity.ContainerRegistration}    Microsoft.Practices.Unity.ContainerRegistration
+        LifetimeManager    {Microsoft.Practices.Unity.TransientLifetimeManager}    Microsoft.Practices.Unity.LifetimeManager {Microsoft.Practices.Unity.TransientLifetimeManager}
+        LifetimeManagerType    {Name = "TransientLifetimeManager" FullName = "Microsoft.Practices.Unity.TransientLifetimeManager"}    System.Type {System.RuntimeType}
+        MappedToType    {Name = "SmartClientDatabase" FullName = "Microsoft.Practices.SmartClient.EnterpriseLibrary.SmartClientDatabase"}    System.Type {System.RuntimeType}
        Name    "QueueDatabase"    string
+        RegisteredType    {Name = "Database" FullName = "Microsoft.Practices.EnterpriseLibrary.Data.Database"}    System.Type {System.RuntimeType}
+        Non-Public members       

 

However, in my console app this is just not there - only the 'LocalSqlServer' instance (presumably from machine.config) is being resolved by the Unity container. However, the error message that I get shows that the config is being loaded because the error message is 'Activation error occured while trying to get instance of type Database, key "QueueDatabase"' - so it knows it is looking for a database called "QueueDatabase" but perhaps, for whatever reason, it cannot resolve the runtime type specified in the providerMapping?

One thing I have just discovered which is at the root of this - I don't think the app.config is being loaded at all - I can make any changes to this file (amending any of the type values to something random) and I do not get an exception as you would expect. I can say categorically that the config is there in the runtime bin folder and is correct. What is going on?

I really appreciate you looking at this for me - it's been two days of frustration and no progress!

Regards,

Chris

 

Feb 23, 2012 at 3:25 PM

Chris, it sounds like you've checked all the right things.  If the type cannot be resolved I would expect to see a different error message.  Something like:

Unhandled Exception: System.ArgumentException: The type 'Microsoft.Practices.SmartClient.EnterpriseLibrary.SmartClientDatabase, Microsoft.Practices.SmartClient.EnterpriseLibrary' cannot be resolved. Please verify the spelling is correct or that the full type name is provided.

That's why it looks like an issue loading the configuration.  The other possibility is a problem with the provider factory but you are using an existing provider name and an other application on the same machine is running so that seems like it's configured properly (in machine.confg).

Is it possible to upload your small console application that reproduces the issue?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Feb 23, 2012 at 8:21 PM

Hi Randy, please find a zipped WinForms project attached.

Regards,

Chris

From: randylevy [email removed]
Sent: 23 February 2012 16:25
To: chris.lewis@exentra.co.uk
Subject: Re: Old chestnut! The type Database cannot be constructed. You must configure the container to supply... [entlib:340945]

From: randylevy

Chris, it sounds like you've checked all the right things. If the type cannot be resolved I would expect to see a different error message. Something like:

Unhandled Exception: System.ArgumentException: The type 'Microsoft.Practices.SmartClient.EnterpriseLibrary.SmartClientDatabase, Microsoft.Practices.SmartClient.EnterpriseLibrary' cannot be resolved. Please verify the spelling is correct or that the full type name is provided.

That's why it looks like an issue loading the configuration. The other possibility is a problem with the provider factory but you are using an existing provider name and an other application on the same machine is running so that seems like it's configured properly (in machine.confg).

Is it possible to upload your small console application that reproduces the issue?

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Feb 27, 2012 at 7:51 AM

Many thanks to Randy Levy of Enterprise Library Support for finding the solution to this problem. I've posted the solution to my problem below in case it helps anyone else.

Here is a copy of his email:

"Hi Chris,

If I remove the provider factory entry from machine.config (on my machine) I do get a similar error to yours.

Try adding the provider factory to the project's app.config:

    <DbProviderFactories>

      <add name="Microsoft SQL Server Compact Data Provider" invariant="System.Data.SqlServerCe.3.5" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>

    </DbProviderFactories>

Let me know how it goes."

Note that this entry goes into the <system.data/> section of the app.config file.

Thanks again Randy, this is much appreciated.

Chris

Feb 27, 2012 at 9:03 PM
Edited Feb 28, 2012 at 1:42 PM

Good to hear that your issue is resolved.

Just for completeness: if you do add the above configuration but that entry is already set in machine.config then you will get an error:

System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for system.data: 
Column 'InvariantName' is constrained to be unique. Value 'System.Data.SqlServerCe.3.5' is already present.
WindowsFormsApplication1.exe.Config line 6) ---> System.Data.ConstraintException: Column 'InvariantName' is constrained to be unique.
Value 'System.Data.SqlServerCe.3.5' is already present.

To avoid this then clear the provider factories or remove the factory you are configuring.  The configuration would be:

<system.data>
  <DbProviderFactories>
    <remove invariant="System.Data.SqlServerCe.3.5" />
    <add name="Microsoft SQL Server Compact Data Provider" 
          invariant="System.Data.SqlServerCe.3.5" 
          description=".NET Framework Data Provider for Microsoft SQL Server Compact" 
          type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=3.5.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91"/>
  </DbProviderFactories>
</system.data>

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com

Dec 2, 2012 at 11:12 AM

Hi,

I am getting the below error to connect oracle DB.

System.InvalidOperationException: The type Database cannot be constructed. You must configure the container to supply this value.

<

 

dataConfiguration defaultDatabase="OracleConnection"

>

<

 

providerMappings

>

<

 

add databaseType="Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Oracle.DataAccess.Client"

/>

</

 

providerMappings

>

</

 

dataConfiguration

>

 

<

 

connectionStrings

>

 

<

 

add name="OracleConnection" connectionString="User Id=userid;Password=xxxxxx;DataSource=yyyyyy" providerName="Oracle.DataAccess.Client"

/>

 

</

 

connectionStrings

>

Regards,

Mano

Dec 3, 2012 at 4:36 AM
Edited Dec 3, 2012 at 4:36 AM

@mracharjya, I created a new post for your issue.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com