2

Registering DbContext in ASP.NET MVC Application as InstancePerRequest. (IoC Autofac)

builder.RegisterType<ADbContext>().As<IADbContext>().InstancePerRequest();

Using inside BService

public class BService : IBService
{
    readonly IADbContext _dbContext;
    public BService(IADbContext dbContext)
    {
        _dbContext = dbContext;
    }
}

Trying to register IBService as Singleton.

builder.RegisterType<BService>().As<IBService>().SingleInstance();

Obviously, this gives me an error

No scope with a tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested.

Simplest solution is to register IBService as InstancePerRequest, but there is no reason having PerRequest IBService rather than error message mentioned above.

How can i use PerRequest DbContext inside Singleton service ?

5
  • 1
    Short answer: you can't. You would have to inject the context into the singleton for every request. Honestly, this feels like a code smell, perhaps you need to rethink your setup? Commented Sep 15, 2016 at 10:31
  • @DavidG Probably, could you suggest best practice ? Commented Sep 15, 2016 at 10:32
  • 1
    I don't think it's about best practice here, but I do think if you are messing with a context, then a singleton is probably not a good idea. Contexts need to be created as late as possible and destroyed as quickly as possible. Also, they do not support concurrency, you will get some weird errors if 2 requests try to hit it at the same time. Commented Sep 15, 2016 at 10:35
  • @DavidG Thanks, so use PerRequest services ? or having some Factory class which will return new context everytime requested ? Commented Sep 15, 2016 at 10:37
  • 1
    I guess that depends on your use case. Generally I go with services per request unless they are expensive to create (which is very rare) Commented Sep 15, 2016 at 10:38

1 Answer 1

1

First attempt, you can inject IContainer into BService. But this will look like Service locator pattern, which is not good. Otherwise, you can define factory interface

public interface IFactory<T>
{
    T GetInstance();
}

Then implement it and register

public class SimpleFactory<T> : IFactory<T>
{
    private IContainer _container;

    public SimpleFactory(IContainer container)
    {
        _container = container;     
    }

    public T GetInstance()
    {
        return _container.Resolve<T>();
    }
}

public class DbContextFactory : SimpleFactory<IADbContext>
{   
    public DbContextFactory(IContainer container):base(container)
    {   
    }
}

Finally, use this factory in your singletone

public class BService : IBService
{
    IADbContext _dbContext =>  _dbContextFactory.GetInstance();
    IFactory<IADbContext> _dbContextFactory

    public BService(IFactory<IADbContext> dbContextFactory)
    {
        _dbContextFactory = dbContextFactory;
    }
}

Each time, when you want to acess to context inside singletone, it will pass this request to IoC container, which able to return context per request.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.