Managing DB Connection with Autofac

852 views
Skip to first unread message

David Russell

unread,
Oct 27, 2014, 8:24:39 AM10/27/14
to aut...@googlegroups.com

Hi

I am having a problem, up until now everything was fine, however I have a part which uses ajax, it looks through the html and every time it finds whats its looking for it, sends an ajax request to the controller, which then uses autofac to  connect to the database and build a html partial which will be returned.

Now it works if it only finds 1 thing in the html, but as soon as it finds one it causes as error, which if down to autofac and the db connection being disposed from the first thing found.

I am a little lost and would appreciate some help, i have looked at the autofac site which seems a little unfinished and I am none the wiser.

I have tried the following;

builder.Register(c => new MyContext()).As<IUnitOfWork>().SingleInstance();

builder.Register(c => new MyContext()).As<IUnitOfWork>().ExternallyOwned();

Just realised that in the part I have an error I am using MVC's DependencyResolver.Current.GetService, I am not having this issue with Autocompletes which doesn't use the DependencyResolver

Any information would be appriciated.

Kendall Bennett

unread,
Oct 27, 2014, 11:12:31 AM10/27/14
to <autofac@googlegroups.com>
Why would you be using a single instance of your database context? You should be getting a new unit of work for every web request and disposing of it when the request is finished. Otherwise it would not be possible to have requests running in parallel.

Regards,

Sent from my iPad Air!

--
You received this message because you are subscribed to the Google Groups "Autofac" group.
To unsubscribe from this group and stop receiving emails from it, send an email to autofac+u...@googlegroups.com.
To post to this group, send email to aut...@googlegroups.com.
Visit this group at http://groups.google.com/group/autofac.
For more options, visit https://groups.google.com/d/optout.

David Russell

unread,
Oct 27, 2014, 4:12:30 PM10/27/14
to aut...@googlegroups.com, kend...@amain.com
Hi

Thanks for the info, I tried it becauses that what I red would work, and it worked until now.

I also tried:

builder.Register(c => new MyContext()).As<IUnitOfWork>().InstancePerHttpRequest()

and that didn't work, which is why I tried the other two options.

If you have a link to some docs or examples, it would appriciated as I am none the wiser on how to fix it.

Kind regards
Dave

Kendall Bennett

unread,
Oct 27, 2014, 4:23:33 PM10/27/14
to David Russell, aut...@googlegroups.com
If it does not work with instance per http request, I would need more details on how your code is written. 

Regards,

Kendall Bennett
CEO & Co-Founder
www.AMain.com | 530-894-0797 | 800-705-2215 
424 Otterson Drive, Chico, California 95928

David Russell

unread,
Oct 27, 2014, 4:52:49 PM10/27/14
to aut...@googlegroups.com
Just remembered the reason it doesn't work with InstancePerHttpRequest, is because I use IQueryable and IEnumerable

and I get the error:

The operation cannot be completed because the DbContext has been disposed.

However here is the code:

The error I am getting is

An error occurred while executing the command definition. See the inner exception for details.

Since its an ajax call I have no idea how to get more detail, since the browser only has an alert popup with "error" in it, the error occurs on this

public StockSupplier GetById(int id, int companyId)
        {

            return _repository.Table
                                .Where(t => t.Id == id && t.CompanyId == companyId)
                                .FirstOrDefault();

        }

everything runs fine when the code executes the first time, its only when the code hits the above code the second time that is has an error.

This is how I get to the code above

private static ISupplierService _supplierService = DependencyResolver.Current.GetService<ISupplierService>();
public static CreateAndUpdateStockOrderViewModel BlankViewModel(this CreateAndUpdateStockOrderViewModel model, int supplierId)
        {
            model.AddEssentials();

            //Add Supplier Info

            var supplier = _supplierService.GetById(supplierId, model.CompanyId);

            model.SupplierName = supplier.Name;
            model.SupplierId = supplier.Id;

            model.OrderDate = DateTime.Now;
            model.DeliveryDate = DateTime.Now;

            return model;
        }
DiConfig

public static void RegisterDependencies()
        {
            #region DI

            var builder = new ContainerBuilder();
            builder.RegisterControllers(typeof(MvcApplication).Assembly);


            //Register Context
            //builder.Register(c => new MyContext()).As<IUnitOfWork>().InstancePerLifetimeScope();

            builder.Register(c => new MyContext()).As<IUnitOfWork>().SingleInstance();


            //Repositories
            builder.RegisterGeneric(typeof(BaseRepository<>)).As(typeof(IBaseRepository<>)).InstancePerHttpRequest();
            
     //Service Layer

            builder.RegisterType<CompanyLocationService>().As<ICompanyLocationService>().InstancePerHttpRequest();
            builder.RegisterType<CompanyService>().As<ICompanyService>().InstancePerHttpRequest();
            builder.RegisterType<ResourceService>().As<IResourceService>().InstancePerHttpRequest();
            builder.RegisterType<LocationService>().As<ILocationService>().InstancePerHttpRequest();
            builder.RegisterType<WebAccountService>().As<IWebAccountService>().InstancePerHttpRequest();
            builder.RegisterType<TaxService>().As<ITaxService>().InstancePerHttpRequest();
            builder.RegisterType<StockService>().As<IStockService>().InstancePerHttpRequest();
            builder.RegisterType<StockFeatureService>().As<IStockFeatureService>().InstancePerHttpRequest();
            builder.RegisterType<StockBrandService>().As<IStockBrandService>().InstancePerHttpRequest();
            builder.RegisterType<StockTitleOptionService>().As<IStockTitleOptionService>().InstancePerHttpRequest();
            builder.RegisterType<StockOptionTypeService>().As<IStockOptionTypeService>().InstancePerHttpRequest();
            builder.RegisterType<ProductService>().As<IProductService>().InstancePerHttpRequest();
            builder.RegisterType<WebsiteService>().As<IWebsiteService>().InstancePerHttpRequest();
            builder.RegisterType<SettingService>().As<ISettingService>().InstancePerHttpRequest();
            builder.RegisterType<SizeChartService>().As<ISizeChartService>().InstancePerHttpRequest();
            builder.RegisterType<StockSupplierService>().As<IStockSupplierService>().InstancePerHttpRequest();
            builder.RegisterType<StockOrderService>().As<IStockOrderService>().InstancePerHttpRequest();
            builder.RegisterType<WebsiteGroupService>().As<IWebsiteGroupService>().InstancePerHttpRequest();
            builder.RegisterType<WebsiteSectionService>().As<IWebsiteSectionService>().InstancePerHttpRequest();
            builder.RegisterType<WebsiteCategoryService>().As<IWebsiteCategoryService>().InstancePerHttpRequest();
            builder.RegisterType<IPriceGroupService>().As<IPriceGroupService>().InstancePerHttpRequest();
            builder.RegisterType<ForumService>().As<IForumService>().InstancePerHttpRequest();
            builder.RegisterType<ArticleService>().As<IArticleService>().InstancePerHttpRequest();
            builder.RegisterType<FileService>().As<IFileService>().InstancePerHttpRequest();
            builder.RegisterType<EmployeeService>().As<IEmployeeService>().InstancePerHttpRequest();
            builder.RegisterType<PriceGroupService>().As<IPriceGroupService>().InstancePerHttpRequest();
            //builder.RegisterType<TeamService>().As<ITeamService>().InstancePerHttpRequest();

            //builder.RegisterType<NotificationService>().As<INotificationService>().InstancePerHttpRequest();
            //builder.RegisterType<ClanService>().As<IClanService>().InstancePerHttpRequest();
            //builder.RegisterType<EmailService>().As<IEmailService>().InstancePerHttpRequest();
            //builder.RegisterType<FileManagerService>().As<IFileManagerService>().InstancePerHttpRequest();
            //builder.RegisterType<ForumService>().As<IForumService>().InstancePerHttpRequest();
            //builder.RegisterType<ArticleService>().As<IArticleService>().InstancePerHttpRequest();
            ////builder.RegisterType<MatchService>().As<IMatchService>().InstancePerHttpRequest();
            //builder.RegisterType<PersonService>().As<IPersonService>().InstancePerDependency();
            //builder.RegisterType<ChatService>().As<IChatService>().InstancePerDependency();
            //builder.RegisterType<SubscriptionService>().As<ISubscriptionService>().InstancePerHttpRequest();
            //builder.RegisterType<HubService>().As<IHubService>().InstancePerHttpRequest();
            //builder.RegisterType<ChatHub>().InstancePerLifetimeScope(); 

            //builder.RegisterType<ChatHub>().ExternallyOwned();
            var container = builder.Build();

            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
            // Create the depenedency resolver.
            //var resolver = new AutofacDependencyResolver(container);

            // Configure SignalR with the dependency resolver.
            //GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);


            //GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(container);
            //RouteTable.Routes.MapHubs();
            // See IContainer for definition of the container variable


            #endregion
        }

Hope that helps

Kind regards
Dave




--
You received this message because you are subscribed to a topic in the Google Groups "Autofac" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/autofac/_XJnTCVFzEM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to autofac+u...@googlegroups.com.

Kendall Bennett

unread,
Oct 27, 2014, 5:17:54 PM10/27/14
to aut...@googlegroups.com
Here is your problem:

private static ISupplierService _supplierService = DependencyResolver.Current.GetService<ISupplierService>();
You cannot store instance per request items in static variables, or they hang around between requests. So only the first request will get a DB context, while subsequent ones will re-use the old one (which is now disposed).

Basically when developing web application code, avoid static variables and functions AT ALL COSTS. Anything stored in a static is going to have to be thread safe and/or guarded across threads, so unless you have a specific need to store something statically, never do it. IIS will always guarantee that no two threads can be in the same code at the same time, so long as you are using instance variables. So in short there are legit reasons to use static's in code (for cache and performance reasons), but 99 times out of 100 it not a good idea.

Also you should not be resolving anything via the dependency resolver; you should be using Autofac to inject the services you need into your classes either via constructor injection or property injection.

Regards,

Kendall Bennett
CEO & Co-Founder
www.AMain.com | 530-894-0797 | 800-705-2215 
424 Otterson Drive, Chico, California 95928

David Russell

unread,
Oct 27, 2014, 5:32:44 PM10/27/14
to aut...@googlegroups.com
Hi

Thanks for the info, so I have two questions:

Since I get an error using InstancePerHttpRequest due to IQueryable, what should I be using.

I can't use a constructor in a static method which is why I used the dependency resolver, so how I do fix the issue.

The static methods are used for all my mapping, in extention methods.

Kind regards
Dave

Kendall Bennett

unread,
Oct 27, 2014, 6:34:09 PM10/27/14
to aut...@googlegroups.com
I am not familiar enough with using Entity Framework to know what the issue with IQueryable might be; whats is the error you are getting?

As for static functions, to use an IoC container your application needs to be refactored to not use any static methods or classes, so everything can be injected when the classes are constructed. If you are stuck with static functions, the only option is to use the dependency resolver to get what you need inside every function call in the static class, because there is no other way to get a different object for every thread.

Regards,

Kendall Bennett
CEO & Co-Founder
www.AMain.com | 530-894-0797 | 800-705-2215 
424 Otterson Drive, Chico, California 95928

David Russell

unread,
Oct 27, 2014, 6:46:05 PM10/27/14
to aut...@googlegroups.com
Hi

The error I get is:


The operation cannot be completed because the DbContext has been disposed

this is when I use return IEnumerable, even if I add .ToList()

All my mapping is done with static classes so its not an option, but there must be a way to solve my issues.

Kind regards
Dave

Alex Meyer-Gleaves

unread,
Oct 28, 2014, 8:14:44 AM10/28/14
to aut...@googlegroups.com
Hi David,

I have to agree with Kendall that some refactoring would be the best solution. Statics and DI are opposing forces.

If refactoring really isn't an option then you could use AutofacDependencyResolver.Current.RequestLifetimeScope inside your static method instead.

var service = DependencyResolver.Current.RequestLifetimeScope.Resolve<ISupplierService>();

You should be able to leave your IUnitOfWork registration as InstancePerHttpRequest. Just make sure you don't store the result in a static variable.

Cheers,

Alex.

David Russell

unread,
Oct 29, 2014, 5:06:09 PM10/29/14
to aut...@googlegroups.com
Hi

Thanks for the info, what about changing my services to a singleton pattern?

Kind regards
Dave
Reply all
Reply to author
Forward
0 new messages