How do I inject the DbContext implementation into the Prism ViewModel constructor?

I am working on WPF Prism application using Unity and Entity Framework. I want to inject my custom DbContext when constructing the ViewModels, so I can use it for the lifetime of the ViewModel. The module that contains the DbContext class is registered with the Bootstrapper, and the DbContext type is registered during Module.Initialize ().

With that said, trying to create ViewModels that inject DbContext throws a runtime error. It says that the IDbConnection needs to be registered. When I register it with a module, it says that DbConnection is an abstract class and cannot be constructed. I must be unaware of how the DbContext should be registered.

Here's where the type is registered in the module:

public class SharedResourcesModule : IModule
{
    IUnityContainer container;


    public SharedResourcesModule(IUnityContainer container)
    {
        this.container = container;
    }


    public void Initialize()
    {
        container.RegisterType<IAuthenticationService, AuthenticationService>();
        container.RegisterType<IDataBaseContext, EFDbContext>();
    }
}

      

And an example ViewModel constructor:

public class ProductContextResultViewModel : ViewModelBase
{
    public ProductContextResultViewModel(IDataBaseContext dataBaseContext)
    {
        this.DataBaseContext = dataBaseContext as EFDbContext;
    }


    private EFDbContext DataBaseContext { get; set; }
}

      

If there is any other detail I can provide, please let me know!

Detailed description of the exception :

Microsoft.Practices.ServiceLocation.ActivationException is not handled by user code HResult = -2146233088 Message = An activation error occurred while trying to get an instance of type Object, key "ProductContextResultView" Source = Microsoft.Practices.ServiceLocation Stack traces: in Microsoft.Practices.ServiceLocation.ServiceLocatorImpl GetInstance (enter serviceType, String key) in c: \ Projects \ CommonServiceLocator \ main \ Microsoft.Practices.ServiceLocation \ ServiceLocatorImplBase.cs: line 53 in Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance [TService] (c: String key) \ Projects \ CommonServiceLocator \ main \ Microsoft.Practices.ServiceLocation \ ServiceLocatorImplBase.cs: line 103 in Microsoft.Practices.Prism.Regions.RegionNavigationContentLoader.CreateNewRegionItem (String candidTargetContract) InnerException: Microsoft.Practices.Unity.ResolutionFailedException HResult = -2146233088 Message = Failure Resolution, Type = "System.Object", name = "ProductContextResultView". An exception occurred when: when resolving.

Exception: InvalidOperationException - The current type, System.Data.Common.DbConnection, is an abstract class and cannot be constructed. Are you missing a type mapping?

At the time of the exception, the container was:

ContextResultsPane.ProductContextResult.ProductContextResultView resolution, ProductContextResultView (displayed from System.Object, ProductContextResultView) Enable option "viewModel" ContextResultsPane.ProductContextResult.ProductContextResultView designer (ContextResultsPane.ProductContextResult.ProductContextResultViewModel viewModel) ContextResultsPane.ProductContextResult.ProductContextResultViewModel Resolution, (none) the Resolution "dataBaseContext "Constructor ContextResultsPane.ProductContextResult.ProductContextResultViewModel (SharedResources.DataAccess.IDataBaseContext dataBaseContext) Allowing SharedResources.DataAccess.EFDbContext.EFDbContext, (none) (mapped to SharedResources.DataAccesstext.DataAccess.EFDbContext (System.Data.Common.DbConnection connection) System.Data.Common.DbConnection solution, (none)

   Source=Microsoft.Practices.Unity
   NameRequested=ProductContextResultView
   TypeRequested=Object
   StackTrace:
        at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
        at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, String name, IEnumerable`1 resolverOverrides)
        at Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides)
        at Microsoft.Practices.Prism.UnityExtensions.UnityServiceLocatorAdapter.DoGetInstance(Type serviceType, String key)
        at Microsoft.Practices.ServiceLocation.ServiceLocatorImplBase.GetInstance(Type serviceType, String key) in c:\Projects\CommonServiceLocator\main\Microsoft.Practices.ServiceLocation\ServiceLocatorImplBase.cs:line 49
   InnerException: System.InvalidOperationException
        HResult=-2146233079
        Message=The current type, System.Data.Common.DbConnection, is an abstract class and cannot be constructed. Are you missing a type mapping?
        Source=Microsoft.Practices.Unity
        StackTrace:
             at Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForAttemptingToConstructAbstractClass(IBuilderContext context)
             at lambda_method(Closure , IBuilderContext )
             at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
             at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
             at lambda_method(Closure , IBuilderContext )
             at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
             at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
             at lambda_method(Closure , IBuilderContext )
             at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey)
             at Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context)
             at lambda_method(Closure , IBuilderContext )
             at Microsoft.Practices.ObjectBuilder2.DynamicBuildPlanGenerationContext.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context)
             at Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context)
             at Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides)
        InnerException: 

      

+3


source to share


1 answer


Glen Thomas' guide helped me do some more reading and it turns out that Unity uses the most verbose constructor by default. This is the core of the problem, as I had a constructor that required passing a DbConnection for unit testing.

To force Unity to use the default constructor, I changed this ...

container.RegisterType<IDataBaseContext, EFDbContext>();

      



... to that...

container.RegisterType<IDataBaseContext, EFDbContext>(new InjectionConstructor());

      

After the change, it works as intended!

+3


source







All Articles