问题
Using Autofac DI container-
What is the difference between registering a unit of work in my web application as per request to registering it as PerLifetimeScope?
Autofac creates a new scope for each request and by registering the unit of work as PerMatchingScope it will anyways be resolved from the scope created for the request.
If I'm mistaken, please correct me, otherwise, what is the difference?
Moreover, If I register the UoW as PerLifetimeScope, and have a console application that sends mesaages over Tcp/Ip to my web server that require creation of that UoW, how will it be handled?
Thanks!
Edit:
public abstract class EFRepository<T> : IRepository<T>
{
protected readonly DbContext Context;
public EFRepository(DbContext context)
{
Context = context;
}
public abstract List<T> Get();
public void Add(T item)
{
Context.Set<T>().Add(item);
}
public virtual Remove(T item)
{
Context.Set<T>().Remove(item);
}
public void Update(T item)
{
Context.Entry(item).State = EntityState.Modified;
}
public void Dispose()
{
Context.Dispose();
}
public int SaveChanges()
{
return Context.SaveChanges();
}
public T FindById(int id)
{
return Context.Set<T>().Find(id);
}
}
public FoldersRepository : EFRepository<Folder>
{
public FoldersRepository(DbContext context) : base(context) {}
. . .
}
// The main part I don't understand
public class mySingletonDataService : ISingletonDataService
{
private Func<IRepository<Folder>> _foldersRepoFactory;
public mySingletonDataService(Func<IRepository<Folder>> foldersRepositoryFactory)
{
_foldersRepoFactory = foldersRepositoryFactory;
}
public void HandleMessageFromTcpIp (Folder folder)
{
// will _foldersRepoFactory be Null here, if it reaches here from Tcp/Ip, Will the context in the created repository be null ??
using (var folder = _foldersRepoFactory())
{
...
}
}
}
mySingletonDataService registered as singleton,
FoldersRepository registered as PerDependency,
DbContext registed as PerRequest? Is it good for my case?
Edit2:
My application structure is this: my container (LayersContainer is singleton and holds all the application's layers, therefore the layers are also singleton and all their dependencies and so on... When application starts I resolve my container and all the components are resolved as well. My problem is that I don't know how the DbContexts will behave when I get to the SingletonDataService from Layer1.
Hope my problem is clear. The behavior of the DbConext from controllers (Http requests) is quite known. But how will the DbContexts behave when handling requests from the remote application over Tcp/Ip? Will it work as DbContext per transaction as we want it to work?
回答1:
PerLife Time Scope
>Per Matching Lifetime Scope
>Per Request
this order more general to more specific.
Per Request
creates 'request' taged Per Matching Lifetime Scope
and it manages lifetime for you.
Per Matching Lifetime Scope
creates taged PerLifeTimeScope
. This is suitable, if you have nested life time scopes.
If you register a type with this scope, you can't resolve the type in another life timescope which does not have same tag (which also parent lifetimescopes do not have this tag). So it gives you more control on Per LifeTime Scope
.
Per LifeTime Scope
creates an object and the object is shared by all in same lifetimescope.
Per Depency
creates a different object everytime when you resolve. This is not shared.
If we come in your question:
Everytime _foldersRepoFactory()
is called new FoldersRepository
object is created and DbContext
object is created in your base class constructor. But DbContext
object is just created 1 time in a request and shared by all others.
I use one more _foldersRepoFactory()
in your method to explain better.
public void HandleMessageFromTcpIp (Folder folder)
{
// will _foldersRepoFactory be Null here, if it reaches here from Tcp/Ip, Will the context in the created repository be null ??
using (var folder = _foldersRepoFactory())
{
...
}
using (var folder = _foldersRepoFactory())
{
...
}
}
Let's say you have a request and you resolve mySingletonDataService
in this request. First Autofac container creates mySingletonDataService
(if it's not created) this stays all life time.
For first _foldersRepoFactory()
is called, Autofac Container creates new FoldersRepository
and DbContext
objects.
For Second _foldersRepoFactory()
is called, Autofac Container crates new FoldersRepository
object but it uses the before DbContext
object (not new DbContext
is created) because they are in same request life time scope.
After request finished, your mySingletonDataService
object stays; your 2 FoldersRepository
and 1 DbContext
objects is disposed (Let's assume GC collects).
You can't use Per Request
because of Layer 1. You can use Per Lifetime Scope
. For Layer 3 it will resolved in request lifetime scope so it will act like Per Request
. You should be careful while resolving your type in Layer1 you sould begin new lifetimescope.
Other than this everthing is ok because you are using Func<IRepository<Folder>>
so it will not stick with singleton.
Note:
Can you make it readonly
to be sure we are not changing it at runtime.
private Func<IRepository<Folder>> _foldersRepoFactory;
来源:https://stackoverflow.com/questions/35471559/autofac-perlifetimescope-vs-perrequest-in-web-applications