getting error "The type Database cannot be constructed. You must configure the container to supply this value"

Dec 21, 2011 at 10:36 AM

hi

I do recently upgraded my entlib 1.0 application to  entlib5.0 . after that am getting error as "The type Database cannot be constructed. You must configure the container to supply this value". please find the code snippet below:

 

rotected DatabaseProviderFactory ServerDatabaseFactory;
   protected DASDalDatabase(string serverConfigSection, System.Security.Principal.WindowsIdentity windowsIdentity)
            {
                try
                {
                    string pagDBConfigFile;
                    #region Unused-Commented code
                    // v-pchett : Added code to impersonate the actual user to retreive the login id

                    //if (windowsIdentity == null)
                    //{
                    //    WindowsPrincipal wp = (WindowsPrincipal)Thread.CurrentPrincipal;
                    //    WindowsIdentity wi = (WindowsIdentity)wp.Identity;
                    //    WindowsImpersonationContext wc = wi.Impersonate();

                    //    // Get the current logged on user User
                    //    this.usingIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();

                    //    // Undo the impersonation							
                    //    wc.Undo();
                    //}
                    //else
                    //{
                    //    usingIdentity = windowsIdentity;

                    //}
                    #endregion


                    // We need to locate this file. These pag config files don't seem to be quite compatible with
                    // V2 of the framework. Shortest path was to use a third file rather than figure out what was 
                    // wrong and port the PAG configuration application blocks. This will find the file (as long as it's
                    // called pag.config. "pag" is located in app.cofig.

                    bool found = false;
                    //					string[] keys = System.Configuration.ConfigurationSettings.AppSettings.AllKeys;
                    string[] keys = System.Configuration.ConfigurationManager.AppSettings.AllKeys;
                    foreach (string s in keys)
                    {
                        if (s == "pathPag")
                        {
                            found = true;
                            break;
                        }
                    }

                    if (found)
                    {
                        //	pagDBConfigFile = System.Configuration.ConfigurationSettings.AppSettings["pathPag"];
                        pagDBConfigFile = System.Configuration.ConfigurationManager.AppSettings["pathPag"];
                    }
                    else
                    {
                        if (System.Web.HttpContext.Current != null)
                        {
                            pagDBConfigFile = System.Web.HttpContext.Current.Request.PhysicalApplicationPath;
                        }
                        else
                        {
                            // assume its as winform
                            pagDBConfigFile = Path.GetDirectoryName(this.GetType().Module.FullyQualifiedName);
                        }
                    }

                    if (pagDBConfigFile.ToCharArray()[pagDBConfigFile.Length - 1] != '\\') pagDBConfigFile += "\\";

                    //					pagDBConfigFile += System.Configuration.ConfigurationSettings.AppSettings["pag"];
                    pagDBConfigFile += System.Configuration.ConfigurationManager.AppSettings["pag"];

                    string mapconfigfile = @pagDBConfigFile;
                    // This database factory helps us create a connection to a database that doesn't happen to be the default
                    // database. This plus the string (next line) locate it and build the connection string.
                    //kiran-19/12/2011
                    //  ServerDatabaseFactory = new PAG.Data.DatabaseProviderFactory(new ConfigurationContext(pagDBConfigFile));
                    
                    ServerDatabaseFactory = new DatabaseProviderFactory(new Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource(mapconfigfile));
                    // This refers to a string in the pag.config file which identifies a section that describes the server connection.
                    // It is used along with the database factory above to create a correct connection to the server..
                    
                    DatabaseServer = serverConfigSection;
                  
                }
                catch (System.Exception ex)
                {
                    throw (new DASException("System Exception", ex));
                }
            }
//Database is initiating at here

  public SqlDatabase GetADatabase()
            {
                try
                {
                    //getting error here

                    Database dbs = ServerDatabaseFactory.Create("svkiran");
                    DatabaseServer = dbs.GetType().FullName;
                

                    return (PAG.Data.Sql.SqlDatabase)ServerDatabaseFactory.Create(DatabaseServer);
                }
                catch (System.Exception ex)
                {
                    throw (new DASException("System Exception", ex));
                }
            }

Can any one please let me know the solution how to resolve this.

Dec 21, 2011 at 2:46 PM

I would recommend reading up on Enterprise Library 5 Data Access.  See the Enterprise Library 5.0 Developers Guide Chapter 2 - Much ADO about Data Access since the approach is different than in 1.1.

It's not clear to me what this code is trying to do:

Database dbs = ServerDatabaseFactory.Create("svkiran");
DatabaseServer = dbs.GetType().FullName;

return (PAG.Data.Sql.SqlDatabase)ServerDatabaseFactory.Create(DatabaseServer);

 

The first line retrieves the Database defined in the configuration with a connectionString named "svkiran".
The second line retrieves the name of the type returned.  This will (probably) be "Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase".
The third line tries to go to the configuration and retrieve a database based on the connection string named "Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase".

You just need to properly configure the database connection and return the Database instance returned from the factory.  I.e.:

return ServerDatabaseFactory.Create("svkiran");

 

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

Jan 5, 2012 at 6:37 PM

Hi Randy - All,

I´m receiving a similar message :

The type HttpContextBase cannot be constructed. You must configure the container to supply this value.

 

Do you know what does this mean when unity says that a container must be configured?... is any part of the container referred specifically?

 

really appreciated your support. brgds! sebastian.

Jan 5, 2012 at 6:45 PM
Edited Jan 5, 2012 at 9:45 PM

It means that Unity doesn't know how to create HttpContextBase.  I.e. it's not registered in the container.

What are you trying to do that is causing this error?  Can you post code and configuration (if applicable)?  

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

Jan 5, 2012 at 7:33 PM

Hi Randy,

thank you for your reply. Well, I´m using HttpContextBase in order to retrieve information like cookies and more. I made a field:

private readonly HttpContextBase _ContextBase;

a constructor:       

public Context(HttpContextBase contextBase,,......)
        {
            this._ContextBase= contextBase;

            this........;

         }

and use it to create an environment for the context of my app. Additionally I registered information eg: container.registertype(Iservice, service) for each Interface and main file that I need to use in my app.

When container.registertype failed to resolve the information appear the legend "you must configure your container"... I faced similar situation with other files - interfaces and services- and solve it when I declared it following that scheme, but based on the fact that httpcontextbase is part of system.web I was not able to reproduce that approach (Interface, service). I´m new in IOC,  sorry if its not so clear... thank you so much.. brgds!

Jan 6, 2012 at 12:08 AM
Edited Jan 6, 2012 at 12:09 AM

It sounds like you want to use a per-request object to manage request state.  One approach that you can use is a HierarchicalLifeTimeManager along with ChildContainers. 

If you are using MVC you could take a look at Unity.MVC3; they use the ChildContainer approach.

The approach is to: 

  1. On application start: create container and register any per-request objects with a HierarchicalLifetimeManager
  2. When a request needs to resolve an object, call CreateChildContainer() and use that container
  3. When the request is complete Dispose the child container

I would recommend looking at the Unity.MVC3 source code.

In this example I use the HttpContextWrapper to contain the HttpContext reference and register that as the implementation of the abstract class HttpContextBase.

1)

        void Application_Start(object sender, EventArgs e)
        {
            IUnityContainer container = new Microsoft.Practices.Unity.UnityContainer();
            container.RegisterType<HttpContextBase, HttpContextWrapper>(new HierarchicalLifetimeManager(),
                new InjectionFactory(c => new HttpContextWrapper(HttpContext.Current)));

            Application["Container"] = container;

            // Code that runs on application startup
        }

2)

    public class MyClass
    {
        Context context;

        public MyClass(Context context)
        {
            this.context = context;
        }
    }

    public class Context
    {
        private HttpContextBase context;

        public Context(HttpContextBase context)
        {
            this.context = context;
        }
    }
   // This would usually happen in a base page or some other part of the application pipeline
   // and store the container for future use during this request.  E.g. save in HttpContext Items
   IUnityContainer container = (Application["Container"] as IUnityContainer).CreateChildContainer();
   var myClass = container.Resolve<MyClass>();

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

Jan 6, 2012 at 12:32 AM

woow! well, what can I say... thank you so much randy!!. I will follow your guidelines... thank you so much!brgds.. sebastian