Unable to Create DbContext per Request with Simple Injector

别来无恙 提交于 2019-12-10 14:24:48

问题


Simple Inject is throwing the following exception when attempting to register my DbContext.

The supplied connection string is not valid, because it contains insufficient mapping or metadata information. Parameter name: connectionString

I'm new to DI and could be missing something fairly obvious. The connection string looks fine. It is the same one that gets used to create the DbContext normally. I was attempting the solution here

public static class SimpleInjectorInitializer
{
    /// <summary>Initialize the container and register 
    // it as MVC3 Dependency Resolver.</summary>
    public static void Initialize()
    {
        var container = new Container();            
        InitializeContainer(container);
        container.RegisterMvcControllers(
            Assembly.GetExecutingAssembly());            
        container.RegisterMvcAttributeFilterProvider();       
        container.Verify();            
        DependencyResolver.SetResolver(
            new SimpleInjectorDependencyResolver(container));
    }

    private static void InitializeContainer(
        Container container)
    {
    }
}

Update: I still haven't solved my issue, but it is very similar to this issue with Ninject

Stack Trace:

System.InvalidOperationException was unhandled by user code
  Message=The configuration is invalid. Creating the instance for type _AccountController failed. Error occurred while trying to get an instance of type _AccountController. The type initializer for 'Web.Controllers._AccountController' threw an exception.
  Source=SimpleInjector
  StackTrace:
       at SimpleInjector.Helpers.Verify(IInstanceProducer instanceProducer, Type serviceType)
       at SimpleInjector.Container.ValidateRegistrations()
       at SimpleInjector.Container.Verify()
       at Web.App_Start.SimpleInjectorInitializer.Initialize() in C:\workspace\BrowsarServer\QARSite\Web\App_Start\SimpleInjectorInitializer.cs:line 24
  InnerException: SimpleInjector.ActivationException
       Message=Error occurred while trying to get an instance of type _AccountController. The type initializer for 'Web.Controllers._AccountController' threw an exception.
       Source=SimpleInjector
       StackTrace:
            at SimpleInjector.InstanceProducers.InstanceProducer.ThrowErrorWhileTryingToGetInstanceOfType(Exception innerException)
            at SimpleInjector.InstanceProducers.InstanceProducer.GetInstance()
            at SimpleInjector.Helpers.Verify(IInstanceProducer instanceProducer, Type serviceType)
       InnerException: System.TypeInitializationException
            Message=The type initializer for 'Web.Controllers._AccountController' threw an exception.
            Source=Web
            TypeName=Web.Controllers._AccountController
            StackTrace:
                 at Web.Controllers._AccountController..ctor()
                 at lambda_method(Closure )
                 at SimpleInjector.InstanceProducers.InstanceProducer.GetInstance()
            InnerException: System.ArgumentException
                 Message=The supplied connection string is not valid, because it contains insufficient mapping or metadata information.
Parameter name: connectionString
                 Source=System.Data.Entity
                 ParamName=connectionString
                 StackTrace:
                      at System.Data.Objects.ObjectContext..ctor(EntityConnection connection, Boolean isConnectionConstructor)
                      at System.Data.Objects.ObjectContext..ctor(String connectionString, String defaultContainerName)
                      at Web.Models.BrowsarEntities..ctor() in C:\workspace\BrowsarServer\QARSite\Web\Models\Browsar.Designer.cs:line 90
                      at Web.Controllers._AccountController..cctor() in C:\workspace\BrowsarServer\QARSite\Web\Controllers\_AccountController.cs:line 15
                 InnerException: System.InvalidOperationException
                      Message=Unable to determine application context. The ASP.NET application path could not be resolved.
                      Source=System.Data.Entity
                      StackTrace:
                           at System.Data.Metadata.Edm.AspProxy.GetBuildManagerReferencedAssemblies()
                           at System.Data.Metadata.Edm.DefaultAssemblyResolver.GetAllDiscoverableAssemblies()
                           at System.Data.Metadata.Edm.DefaultAssemblyResolver.GetWildcardAssemblies()
                           at System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.LoadResources(String assemblyName, String resourceName, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
                           at System.Data.Metadata.Edm.MetadataArtifactLoaderCompositeResource.CreateResourceLoader(String path, ExtensionCheck extensionCheck, String validExtension, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
                           at System.Data.Metadata.Edm.MetadataArtifactLoader.Create(String path, ExtensionCheck extensionCheck, String validExtension, ICollection`1 uriRegistry, MetadataArtifactAssemblyResolver resolver)
                           at System.Data.Metadata.Edm.MetadataCache.SplitPaths(String paths)
                           at System.Data.Common.Utils.Memoizer`2.<>c__DisplayClass2.<Evaluate>b__0()
                           at System.Data.Common.Utils.Memoizer`2.Result.GetValue()
                           at System.Data.Common.Utils.Memoizer`2.Evaluate(TArg arg)
                           at System.Data.EntityClient.EntityConnection.GetMetadataWorkspace(Boolean initializeAllCollections)
                           at System.Data.Objects.ObjectContext.RetrieveMetadataWorkspaceFromConnection()
                           at System.Data.Objects.ObjectContext..ctor(EntityConnection connection, Boolean isConnectionConstructor)
                      InnerException: System.Reflection.TargetInvocationException
                           Message=Exception has been thrown by the target of an invocation.
                           Source=mscorlib
                           StackTrace:
                                at System.RuntimeMethodHandle._InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, SignatureStruct& sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
                                at System.RuntimeMethodHandle.InvokeMethodFast(IRuntimeMethodInfo method, Object target, Object[] arguments, Signature sig, MethodAttributes methodAttributes, RuntimeType typeOwner)
                                at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, Boolean skipVisibilityChecks)
                                at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
                                at System.Data.Metadata.Edm.AspProxy.GetBuildManagerReferencedAssemblies()
                           InnerException: System.InvalidOperationException
                                Message=This method cannot be called during the application's pre-start initialization stage.
                                Source=System.Web
                                StackTrace:
                                     at System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled()
                                     at System.Web.Compilation.BuildManager.GetReferencedAssemblies()
                                InnerException: 

回答1:


The root cause is burried deep down in the inner exceptions. When inspecting the stack trace, you will be able to find the cause of this. The reason is in the following two inner exceptions:

InvalidOperationException: Unable to determine application context. The ASP.NET application path could not be resolved.

and:

InvalidOperationException: This method cannot be called during the application's pre-start initialization stage.

In other words, this exception is caused by a timing problem. I'm not sure if you can change your connection string to solve this, but you can also move your initalization to a later moment in starting the application. You can do this as follows:

  1. Remove the [assembly: WebActivator.PreApplicationStartMethod] (top line) of the SimpleInjectorInitializer.cs class.
  2. Add a call to the SimpleInjectorInitializer.Initialize() method in the Application_Start() event of the global asax.

After doing this, initializing (and especially, verifying) of the object graph is done after the pre-init state, which seems to be too early for EF in an ASP.NET environment.

Another option is to remove the container.Verify(); call from the SimpleInjectorInitializer.Initialize method, since it is the early verification process that is killing you. However, please read this Verify the container’s configuration first, to see alternatives, before doing so.




回答2:


Although you use a class DbContext it looks like it is derived from ObjectContext. In that case you should use an EntityConnectionStringBuilder to build the connection string.




回答3:


You may be missing some of the metadata information in your connection string. For example entity framework has some special metadata in the connection string, see sample below:

<add name="MyEntities" connectionString="metadata=res://*/MyEntitiesStore.csdl|res://*/MyEntitiesStore.ssdl|res://*/MyEntitiesStore.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=<your server>;Initial Catalog=<your DB>;Integrated Security=False;User ID=<user>;Password=<pass>;MultipleActiveResultSets=True&quot;" 
   providerName="System.Data.EntityClient" />


来源:https://stackoverflow.com/questions/11042357/unable-to-create-dbcontext-per-request-with-simple-injector

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!