DatabaseAssemblerAttribute and IDatabaseAssembler

Topics: Data Access Application Block
May 10, 2010 at 2:00 PM

Hi,

I'm upgrading from Enterprise Library 4.0 to Enterprise Library 5.0.
I have a class that uses DatabaseAssemblerAttribute and another that uses IDatabaseAssembler.
When I added a reference to Microsoft.Practices.EnterpriseLibrary.Data I get a error message:

Cannot resolve 'IDatabaseAssembler'

I have downloaded the source code for Enterprise Library 5.0 and
noticed that that databaseAssemblerAttribute and IDatabaseAssembler
aren’t a part of Enterprise Library anymore.
I haven’t been able to find any info about this in "braking changes".

Where can I found more info about this?

 

May 11, 2010 at 1:57 AM

The assemblers were removed as entlib now uses dependency injection to create and manage the different entlib objects.  You no longer need to decorate your custom database with a databaseassembler.  Instead, you need to decorate it with the ConfigurationElementType attribute and specify the configuration element your custom database will use.   For e.g., in the case of a  SqlDatabase, it uses SqlDatabaseData as the ConfigurationElementType.   This is included in the documentation. Check out Extending and Modifying the Data Access Application Block -> Adding a New Application Block Database Provider.

 

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

May 12, 2010 at 8:28 PM
Edited May 12, 2010 at 8:54 PM

Hi,

It seems that I'm using similar approach as Andreas. My case is that connection string should be retrieved in another way than storing in app.config file. However I receive error when trying to do something like this.


Maybe there is easier way to "inject" different connection string rather than in app.config?

 


app.config:

    <dataConfiguration defaultDatabase="LoggingDb">
        <providerMappings>
            <add databaseType="eldemo.DatabaseProvider, eldemo, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
                name="Custom.Provider" />
        </providerMappings>
    </dataConfiguration>
    <connectionStrings>
        <add name="LoggingDb" connectionString=""
            providerName="Custom.Provider" />
    </connectionStrings>

 

Provider:

[ConfigurationElementType(typeof (SqlDatabaseData))]
public class DatabaseProvider : SqlDatabase
{
// only inherited constructors
}


exception:

An error occurred in application eldemo.vshost.exe in the Enterprise Library Logging Application Block.
A configuration failure occurred while logging.
The exception that occured was: Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type LogWriter, key "" ---> Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter", name = "(none)".
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.Logging.LogWriterImpl,LogWriter.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter, (none))
  Resolving parameter "structureHolder" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterImpl(Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder structureHolder, Microsoft.Practices.EnterpriseLibrary.Logging.Instrumentation.ILoggingInstrumentationProvider instrumentationProvider, Microsoft.Practices.EnterpriseLibrary.Logging.ILoggingUpdateCoordinator updateCoordinator)
    Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder,LogWriterStructureHolder.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder, (none))
    Resolving parameter "traceSources" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder(System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.Logging.Filters.ILogFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] filters, System.Collections.Generic.IEnumerable`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] traceSourceNames, System.Collections.Generic.IEnumerable`1[[Microsoft.Practices.EnterpriseLibrary.Logging.LogSource, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]] traceSources, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource allEventsTraceSource, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource notProcessedTraceSource, Microsoft.Practices.EnterpriseLibrary.Logging.LogSource errorsTraceSource, System.String defaultCategory, System.Boolean tracingEnabled, System.Boolean logWarningsWhenNoCategoriesMatch, System.Boolean revertImpersonation)
      Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogSource,General
      Resolving parameter "traceListeners" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.LogSource(System.String name, System.Collections.Generic.IEnumerable`1[[System.Diagnostics.TraceListener, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] traceListeners, System.Diagnostics.SourceLevels level, System.Boolean autoFlush, Microsoft.Practices.EnterpriseLibrary.Logging.Instrumentation.ILoggingInstrumentationProvider instrumentationProvider)
        Resolving Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper,Database Trace Listener (mapped from System.Diagnostics.TraceListener, Database Trace Listener)
        Resolving parameter "wrappedTraceListener" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper(System.Diagnostics.TraceListener wrappedTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.ILoggingUpdateCoordinator coordinator)
          Resolving Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener,Database Trace Listener‌implementation (mapped from System.Diagnostics.TraceListener, Database Trace Listener‌implementation)
          Resolving parameter "database" of constructor Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener(Microsoft.Practices.EnterpriseLibrary.Data.Database database, System.String writeLogStoredProcName, System.String addCategoryStoredProcName, Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.ILogFormatter formatter)
            Resolving Microsoft.Practices.EnterpriseLibrary.Data.Database,LoggingDb
 ---> System.InvalidOperationException: The type Database cannot be constructed. You must configure the container to supply this value.
   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.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 220
   at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\NamedTypeDependencyResolverPolicy.cs:line 51
   at BuildUp_Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener(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.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 220
   at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\NamedTypeDependencyResolverPolicy.cs:line 51
   at BuildUp_Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.ReconfigurableTraceListenerWrapper(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.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 220
   at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\NamedTypeDependencyResolverPolicy.cs:line 51
   at Microsoft.Practices.Unity.ResolvedArrayWithElementsResolverPolicy.DoResolve[T](IBuilderContext context, IDependencyResolverPolicy[] elementPolicies) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\ResolvedArrayWithElementsResolverPolicy.cs:line 73
   at Microsoft.Practices.Unity.ResolvedArrayWithElementsResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\ResolvedArrayWithElementsResolverPolicy.cs:line 64
   at BuildUp_Microsoft.Practices.EnterpriseLibrary.Logging.LogSource(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.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 220
   at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\NamedTypeDependencyResolverPolicy.cs:line 51
   at Microsoft.Practices.Unity.ResolvedArrayWithElementsResolverPolicy.DoResolve[T](IBuilderContext context, IDependencyResolverPolicy[] elementPolicies) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\ResolvedArrayWithElementsResolverPolicy.cs:line 73
   at Microsoft.Practices.Unity.ResolvedArrayWithElementsResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\ResolvedArrayWithElementsResolverPolicy.cs:line 64
   at BuildUp_Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterStructureHolder(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.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\BuilderContext.cs:line 220
   at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilderCustomization\NamedTypeDependencyResolverPolicy.cs:line 51
   at BuildUp_Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterImpl(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
   --- End of inner exception stack trace ---
   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
   --- End of inner exception stack trace ---
   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]() in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 90
   at Microsoft.Practices.EnterpriseLibrary.Logging.Logger.get_Writer() in e:\Builds\EntLib\Latest\Source\Blocks\Logging\Src\Logging\Logger.cs:line 402

May 12, 2010 at 9:00 PM

I noticed that this even happens if you point "Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" as custom database provider.

May 12, 2010 at 9:30 PM

And I'm aware of this thread - http://entlib.codeplex.com/Thread/View.aspx?ThreadId=210054.

 

May 13, 2010 at 3:01 AM

I think the error happens because it can't create the Database object because it needs a value for the connection string parameter.  Could you verify this by supplying a value to the connectinoString attribute.

Do you have something in mind that you think is an easier way to inject connection strings other than specifying it in config?  How?  

 

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

May 13, 2010 at 7:42 PM

I though it would be the issue - missing connection string. But anyway even config like this is failing with the same error.

<dataConfiguration defaultDatabase="LoggingDb">
        <providerMappings>
            <add databaseType="Microsoft.Practices.EnterpriseLibrary.Data.Sql.SqlDatabase, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="Custom.Provider" />
        </providerMappings>
    </dataConfiguration>
    <connectionStrings>
        <add name="LoggingDb" connectionString="Data Source=localhost;Initial Catalog=ELDEMO;Integrated Security=True;" providerName="Custom.Provider" />
    </connectionStrings>

 

If I switch provider in connection strings element - works fine everything.

Problem is during initialization of custom provider type. Breakpoint is not even hit in constructor of custom type. Is there any chances to get price exception - what excatly went wrong?

 

Anyway how can I achieve this with EL 5.0:

    /// <summary>
    /// </summary>
    [DatabaseAssembler(typeof (MaplDatabaseAssembler))]
    public class DatabaseProvider : Microsoft.Practices.EnterpriseLibrary.Data.Database

 

    public class MaplDatabaseAssembler : IDatabaseAssembler
    {
        public Microsoft.Practices.EnterpriseLibrary.Data.Database Assemble(string name,
                                                                            ConnectionStringSettings
                                                                                connectionStringSettings,
                                                                            IConfigurationSource configurationSource)
        {
            return new SqlDatabase(ConnectionFactory.GetConnectionString("LOGGING"));
        }

}

 

 

 

May 14, 2010 at 1:24 AM

First, create your custom database and decorate it with the ConfigurationElementType attribute.

[ConfigurationElementType(typeof(MyDatabaseProviderData))]
public class MyDatabaseProvider : Database
{
        public MyDatabaseProvider (string connectionString) 
            : base(connectionString) 
        { }
               
       protected override void DeriveParameters(System.Data.Common.DbCommand discoveryCommand)
       {
       }

       //override other methods you need to
}

Next, create the configuration element type class and make sure to override the GetRegistrations method.

public class MyDatabaseProviderData: DatabaseData
{
        public MyDatabaseProviderData(ConnectionStringSettings connectionStringSettings, IConfigurationSource configurationSource)
            : base(connectionStringSettings, configurationSource)
{
}

public override IEnumerable<TypeRegistration> GetRegistrations()
{
            yield return new TypeRegistration<Database>(
                () => new MyDatabaseProviderData(
                    ConnectionString))
            {
                Name = Name,
                Lifetime = TypeRegistrationLifetime.Transient
            };
        }
}

I have a working sample on my machine, if you want a copy, send an email to entlib.support@avanade.com

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

May 14, 2010 at 6:53 AM

Thanks. This example seems more or less acceptable (better than hacking some other places). Your sample code contains some errors but that's fine - it's life :)

However, if I configure your way another interesting exception occours: "Common Language Runtime detected an invalid program."

 

 

An error occurred in application eldemo.vshost.exe in the Enterprise Library Logging Application Block.
A configuration failure occurred while logging.
The exception that occured was: Microsoft.Practices.ServiceLocation.ActivationException: Activation error occured while trying to get instance of type LogWriter, key "" ---> Microsoft.Practices.Unity.ResolutionFailedException: Resolution of the dependency failed, type = "Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidProgramException - Common Language Runtime detected an invalid program.
-----------------------------------------------
At the time of the exception, the container was:

  Resolving Microsoft.Practices.EnterpriseLibrary.Logging.LogWriterImpl,LogWriter.__default__ (mapped from Microsoft.Practices.EnterpriseLibrary.Logging.LogWriter, (none))
 ---> System.InvalidProgramException: Common Language Runtime detected an invalid program.
   at System.Runtime.CompilerServices.RuntimeHelpers._CompileMethod(IRuntimeMethodInfo method)
   at System.Reflection.Emit.DynamicMethod.CreateDelegate(Type delegateType)
   at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.GetBuildMethod() in e:\Builds\Unity\UnityTemp\Compile\Unity\Unity\Src\ObjectBuilder\Strategies\BuildPlan\DynamicMethod\DynamicBuildPlanGenerationContext.cs:line 98
   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 50
   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
   --- End of inner exception stack trace ---
   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
   --- End of inner exception stack trace ---
   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]() in c:\Home\Chris\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 90
   at Microsoft.Practices.EnterpriseLibrary.Logging.Logger.get_Writer() in e:\Builds\EntLib\Latest\Source\Blocks\Logging\Src\Logging\Logger.cs:line 402

May 14, 2010 at 6:57 AM

What is the exact code which throws the exception?  Are you resolving for a LogWriter object?  Please post the code. 

 

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

May 14, 2010 at 7:10 AM
Edited May 14, 2010 at 7:40 AM

Yes exception is thrown when resolving Logger.

Code:

namespace eldemo
{
    [ConfigurationElementType(typeof (MyDatabaseProviderData))]
    public class DatabaseProvider : Database
    {
        public DatabaseProvider(string connectionString, DbProviderFactory dbProviderFactory)
            : base(connectionString, dbProviderFactory)
        {
        }

        public DatabaseProvider(string connectionString, DbProviderFactory dbProviderFactory,
                                IDataInstrumentationProvider instrumentationProvider)
            : base(connectionString, dbProviderFactory, instrumentationProvider)
        {
        }

        protected override void DeriveParameters(DbCommand discoveryCommand)
        {
        }
    }

    public class MyDatabaseProviderData : DatabaseData
    {
        public MyDatabaseProviderData(ConnectionStringSettings connectionStringSettings,
                                      IConfigurationSource configurationSource)
            : base(connectionStringSettings, configurationSource)
        {
        }

        public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<Database>(
                () =>
                new SqlDatabase(DatabaseConnectionProvider.ConnectionString))
                             {
                                 Name = Name,
                                 Lifetime = TypeRegistrationLifetime.Transient
                             };
        }
    }
}

 

 

With this code an excpetion is thrown in "Microsoft.Practices.ObjectBuilder2DynamicMethodConstructorStrategy.GuardTypeIsNonPrimitive()":

        private static void GuardTypeIsNonPrimitive(IBuilderContext context, SelectedConstructor selectedConstructor)
        {
            var typeToBuild = context.BuildKey.Type;
            if(!typeToBuild.IsInterface)
            {
                if(typeToBuild == typeof(string) || selectedConstructor == null)
                {
                    throw new InvalidOperationException(
                        string.Format(
                            CultureInfo.CurrentCulture,
                            Resources.TypeIsNotConstructable,
                            typeToBuild.Name));
                }
            }
        }
    }

 

When "Database" should be built - "selectedConstructor" is null.

Maybe that is if I'm trying to create SqlDatabase (bold in code)?

May 14, 2010 at 7:13 AM

Yes, you should change it to new up your DatabaseProvider class.

 

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

May 14, 2010 at 7:46 AM

Really? Even in your code you are regsitering "Database" type. If so from where can I get connection string settings and config source objects?

I created provider looking at SqlDataProvider code. So during registration provider is returning instance of the SqlDatabase by supplying connection string and instrumentation provider.

The only thing I wanted to achieve is - to return SqlDatabase initialized with connection string from another config source.

 

namespace Microsoft.Practices.EnterpriseLibrary.Data.Sql.Configuration
{
    public class SqlDatabaseData : DatabaseData
    {
        public SqlDatabaseData(ConnectionStringSettings connectionStringSettings, IConfigurationSource configurationSource)
            : base(connectionStringSettings, configurationSource)
        {
        }

        public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<Database>(
                () => new SqlDatabase(
                    ConnectionString,
                    Container.Resolved<IDataInstrumentationProvider>(Name)))
                {
                    Name = Name,
                    Lifetime = TypeRegistrationLifetime.Transient
                };
        }
    }
}

May 14, 2010 at 8:06 AM

The one that you would new up in your GetRegistrations is your custom database which uses your provider data.  In the code you previously posted, you would new up a DatabaseProvider object since it's the one you derived from the DatabaseData.  If you want an SqlDatabase, then you can simply inherit your custom database to SqlDatabase rather than to Database.

Anyway, if you only need your connection string to come from another config, won't using the configSource attribute suffice?

<connectionStrings configSource="anotherConfig.config" />

Note: configSource must be a relative physical path.

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

May 14, 2010 at 8:32 AM

I changed code. Error the same - selectedConstructor is null when creating "Database".

 

namespace eldemo
{
    [ConfigurationElementType(typeof (MyDatabaseProviderData))]
    public class DatabaseProvider : SqlDatabase
    {
        public DatabaseProvider(string connectionString) : base(connectionString)
        {
        }

        public DatabaseProvider(string connectionString, IDataInstrumentationProvider instrumentationProvider)
            : base(connectionString, instrumentationProvider)
        {
        }
    }

    public class MyDatabaseProviderData : SqlDatabaseData
    {
        public MyDatabaseProviderData(ConnectionStringSettings connectionStringSettings,
                                      IConfigurationSource configurationSource)
            : base(connectionStringSettings, configurationSource)
        {
        }

        public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<SqlDatabase>(
                () =>
                new SqlDatabase(DatabaseConnectionProvider.ConnectionString))
                             {
                                 Name = Name,
                                 Lifetime = TypeRegistrationLifetime.Transient
                             };
        }
    }
}

 

I can't use "configSource" attribute as connection string I receive from centralized config source which is not some of the relative sources besides component but some kind of config service for the whole system.

May 14, 2010 at 8:46 AM

But you still didn't change SqlDatabase to DatabaseProvider.

public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<SqlDatabase>(
                () =>
                new SqlDatabase(DatabaseConnectionProvider.ConnectionString))
                             {
                                 Name = Name,
                                 Lifetime = TypeRegistrationLifetime.Transient
                             };
        }

should be

public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<Database>(
                () =>
                new DatabaseProvider(DatabaseConnectionProvider.ConnectionString))
                             {
                                 Name = Name,
                                 Lifetime = TypeRegistrationLifetime.Transient
                             };
        }

Personally, I think you should rename the DatabaseProvider class.  Something close to SqlDatabase.

 

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

May 14, 2010 at 9:01 AM

ok. understood. provder was a bit confused. new code:

namespace eldemo
{
    [ConfigurationElementType(typeof (MyCustomDatabaseData))]
    public class CustomSqlDatabase : SqlDatabase
    {
        public CustomSqlDatabase(string connectionString) : base(connectionString)
        {
        }

        public CustomSqlDatabase(string connectionString, IDataInstrumentationProvider instrumentationProvider)
            : base(connectionString, instrumentationProvider)
        {
        }
    }

    public class MyCustomDatabaseData : DatabaseData
    {
        public MyCustomDatabaseData(ConnectionStringSettings connectionStringSettings,
                                    IConfigurationSource configurationSource)
            : base(connectionStringSettings, configurationSource)
        {
        }

        public override IEnumerable<TypeRegistration> GetRegistrations()
        {
            yield return new TypeRegistration<Database>(
                () =>
                new CustomSqlDatabase(DatabaseConnectionProvider.ConnectionString))
                             {
                                 Name = Name,
                                 Lifetime = TypeRegistrationLifetime.Transient
                             };
        }
    }
}

 

Error the same - null for selectedConstructor.

May 14, 2010 at 9:06 AM
Edited May 14, 2010 at 9:23 AM

Ok, I'm not sure why you're encountering the error.  If you like, you can send me your sample project which repros the error or I could send you my working project. Just send an email to entlib.support@avanade.com so you won't need to post your email address.

 

[update] I've sent the sample project.

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

May 14, 2010 at 10:24 AM

Thanks to Sarah sample project. I figure out that cause of this error was provider name in the app.config file.

It's causing the problem when config is similar to this:

<connectionStrings>

        <add name="LoggingDb" connectionString="" providerName="Custom.Database" />

    </connectionStrings>

<dataConfiguration>

        <providerMappings>

            <add databaseType="Platform.DatabaseProvider, Platform" name="Custom.Database" />

        </providerMappings>

    </dataConfiguration>

 

Should be reconfigured to look something like this:

<connectionStrings>

        <add name="LoggingDb" connectionString="" providerName="System.Data.SqlClient" />

    </connectionStrings>

<dataConfiguration>

        <providerMappings>

            <add databaseType="Platform.DatabaseProvider, Platform" name="System.Data.SqlClient" />

        </providerMappings>

    </dataConfiguration>