error on custom service using ISingletonDependency and autofac

Topics: Writing modules
Oct 15, 2012 at 1:53 PM
Edited Oct 15, 2012 at 2:00 PM

 Hello I am trying to inject a custom Service  in a Controller that implements ISingletonDependency.  This custom service needs to open an external entity framework data repository and grab some data to populate some internal  properties of the service.  The problem is that when the custom service (called AppController) is instantiated and tries to open the EF repository it shows and error saying : 

 Autofac.Core.DependencyResolutionException
 "An exception was thrown while invoking the constructor 'Void .ctor()' on type 'AppController'"
  Inner Exception : {"Unable to resolve assembly 'Intelli.Data.Sys.EFDAL, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.":null}
 
 Stack Trace: 
  at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.<Execute>b__6()
   at Autofac.Core.Lifetime.LifetimeScope.GetOrCreateAndShare(Guid id, Func`1 creator)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Activators.Reflection.AutowiringParameter.<>c__DisplayClass2.<CanSupplyValue>b__0()
   at Autofac.Core.Activators.Reflection.ConstructorParameterBinding.Instantiate()
   at Autofac.Core.Activators.Reflection.ReflectionActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, IEnumerable`1 parameters, Object& instance)
   at Autofac.ResolutionExtensions.TryResolveService(IComponentContext context, Service service, Object& instance)
   at Orchard.Mvc.OrchardControllerFactory.TryResolve[T](WorkContext workContext, Object serviceKey, T& instance) in D:\GiannisDocuments\orchard151\src\Orchard\Mvc\OrchardControllerFactory.cs:line 26
   at Orchard.Mvc.OrchardControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) in D:\GiannisDocuments\orchard151\src\Orchard\Mvc\OrchardControllerFactory.cs:line 71

 It looks like autofac is trying to take over instatiating the EFDAL Repository which is something i do not want.   I simply want to open a custom repository, get the data , and then close it.    Cant i just tell autofac to ignore the ef dal repository ?

This is how my service is implemented : 

 //Custom service interface 
 public interface IAppController : ISingletonDependency
    {
        
 
    }
	 
	// custom service implementation 
	   public class AppController :IAppController
	   
	   {
	   
	    public AppController()
        {
          
            InitAppController();
        }
	   
	   
	     private void InitAppController()
        {
			      //get some data from an entity framework data repository 
			       var cnnstr = "EFConnectionString";
                    using (var db = new DataEntities(startup, cnnstr))  //This is where the autofac error occurs
                     {
                      //get some data from an entity framework data repository 
					  
                    }
	   
	   }
	   
	   
	   }
  
 //mvc Controller 
 public class WorkItemController : Controller
  {
         private readonly IAppController _appController;
	     public IOrchardServices Services { get; private set; }
	     private readonly IContentManager _contentManager;
   public WorkItemController(IContentManager contentManager, IOrchardServices orchardServices,  IAppController appController)
        {
            _contentManager = contentManager;
            Services = orchardServices;
           _appController = appController;
        }
  }

 

 

 

Oct 15, 2012 at 2:52 PM

Issue resolved. 

I had to add the EF dll files in the dependencies folder and it worked!!

had nothing to do with autofac.

Coordinator
Oct 15, 2012 at 4:24 PM

You should avoid singletons like tha plague. What justifies using one in this case?

Oct 15, 2012 at 5:24 PM
Edited Oct 15, 2012 at 8:17 PM

Really ?? I'm surprised.

I am using a singleton for performance reasons.

I want to store some state that i am getting from a custom database in my service and use it in my controllers.

the only reason i used singleton  is to not  hit the database on every request , only once when the shell starts.

What other methods would you propose to save state ?

Store it in the session ?

 

Yiannis

Coordinator
Oct 15, 2012 at 8:25 PM

Err, yes. What you need here is very clearly caching, not a singleton. Seriously, singletons are extremely dangerous for many reasons, my favorite one being that they require thread safe code, which is very, very easy to get wrong. Caching on the other hand is a lot easier to use and does the job much better, as it has expiration, eviction policies, etc.

Here's some reading for you ;)

http://blogs.msdn.com/b/scottdensmore/archive/2004/05/25/140827.aspx

http://tech.puredanger.com/2007/07/03/pattern-hate-singleton/

https://sites.google.com/site/steveyegge2/singleton-considered-stupid

Oct 15, 2012 at 9:10 PM

Hmm,

your observation made me look deeper into the IOrchardService and saw that orchard uses an interesting approach 

to storing the CurrentUser instance.

I'll see if i can adopt a similar pattern.

Always learning new things with Orchard !!.

Thank you.