DbContextScope
DbContextScope copied to clipboard
IOC IDbContextScopeFactory and IAmbientDbContextLocator lifecycle
What should the lifecycles of these two dependencies be when registering with a container. For example singleton, transient, one per web request etc.
I had the same question, how to registering IDbContextScope with autofac?
I too am wondering about this.
We are also wondering what we need to register in Autofac to make this work. We "think" we need to register in Autofac:
- IDbContextFactory and our own implementation for this
- IDbContextScopeFactory and DbContextScopeFactory
- IAmbientDbContextLocator and AmbientDbContextLocator
Also, we are using WCF, which is currently marking our transaction boundary (using autofachostfactory). How does this integrate with WCF and Autofac?
Singleton makes sense
Singleton probably doesn't make sense in AutoFac for web requests because I believe it would be shared across requests.
Since you are using IoC I think you use whatever makes sense for whatever is consuming your service like Mehdi argues. If you are using MVC, have your web app configure the container for web requests. If you build a CLI for your service, you can create the context when your app starts and dispose of it after your command completes and the app exits.
What Mehdi is saying at the core of his article is the service needs to be the one in charge of the lifecycle of the DbContext so you can use transactions. But who's in charge of the life-cycle of the service? Whatever app is making use of the service. A web app is unique because it's technically running 24/7. If you take IoC out of the equation, it might help you think about this better. Just like when Mehdi say's he stopped calling his library a UnitOfWork things became more clear.
Consider if you had to choose manually on when you would new up your service.
Singletons, from my perspective.
It might be helpful to look into ASP.NET Core and how people are doing this over there. https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection DI is a first class citizen now. They might have the same issue as we are trying to solve here or they might not.
For what it's worth, there is nothing wrong with using a scoped lifetime. This library just makes it easy to let your services handle the transactions and also gives your repos easy access to the context without too much passing things around.
Invert the dependency!
Always invert! Don't locate your dependencies, ask for them:
public class Example {
public Func<IDbContext> DbContext { get; set; }
Example(Func<IDbContext> dbContext)
{
DbContext = dbContext;
}
}
Then you need a TransactionManager which will be responsible for creating scopes and threading the right DbContextScope dependency to Func<IDbContext>, like so:
// open a logical transaction
using (TransactionManager.OpenScope())
{
DbContext().Save();
}