使用Autofac DI容器 -
根据PerlifetimeScope注册请求在我的Web应用程序中注册工作单元有什么区别?
Autofac为每个请求创建一个新范围,并通过将工作单元注册为PerMatchingScope,无论如何都将从为请求创建的范围中解析它。
如果我弄错了,请纠正我,否则,有什么区别?
此外,如果我将UoW注册为PerLifetimeScope,并且有一个控制台应用程序通过Tcp / Ip将请求发送到我的Web服务器,需要创建该UoW,它将如何处理?
谢谢!
修改
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注册为singleton,
FoldersRepository注册为PerDependency,
DbContext注册为PerRequest?这对我的情况有好处吗?
编辑2:
我的应用程序结构是这样的:我的容器(LayersContainer是单例并且包含所有应用程序的层,因此层也是单例及其所有依赖项等等...当应用程序启动时我解析我的容器和所有的组件都得到了解决。我的问题是,当我从Layer1进入SingletonDataService时,我不知道DbContexts的行为。
希望我的问题很清楚。来自控制器(Http请求)的DbConext的行为是众所周知的。但是,当通过Tcp / Ip处理来自远程应用程序的请求时,DbContexts将如何表现?它会像每个事务的DbContext一样工作吗?
答案 0 :(得分:1)
PerLife Time Scope
&gt; Per Matching Lifetime Scope
&gt; Per Request
此订单更为通用,更具体。
Per Request
创建“请求”taged Per Matching Lifetime Scope
并为您管理生命周期。
Per Matching Lifetime Scope
创建了t PerLifeTimeScope
。如果您有嵌套的生命周期范围,这是合适的。
如果您使用此范围注册类型,则无法在另一个没有相同标记的生命时间范围内解析该类型(父级生命周期内也没有此标记)。因此,它可以让您更好地控制Per LifeTime Scope
。
Per LifeTime Scope
创建一个对象,所有人在同一生命周期内共享该对象。
Per Depency
都会创建一个不同的对象。这不是共享的。
如果我们提出您的问题:
每次调用_foldersRepoFactory()
时,都会创建新的FoldersRepository
对象,并在基类构造函数中创建DbContext
对象。但DbContext
对象只是在请求中创建了一次,并由所有其他对象共享。
我在你的方法中再使用一个_foldersRepoFactory()
来更好地解释。
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())
{
...
}
}
假设您有请求,并在此请求中解析mySingletonDataService
。第一个Autofac容器创建mySingletonDataService
(如果它没有创建),这将保持一生。
首次调用_foldersRepoFactory()
时,Autofac Container会创建新的FoldersRepository
和DbContext
个对象。
对于第二个_foldersRepoFactory()
被调用,Autofac容器会创建新的FoldersRepository
对象,但它使用之前的DbContext
对象(而不是新的DbContext
),因为它们是相同的请求终身范围。
请求完成后,您的mySingletonDataService
对象会停留;你的2 FoldersRepository
和1 DbContext
个对象被处理掉(我们假设GC收集)。
由于第1层,您无法使用Per Request
。您可以使用Per Lifetime Scope
。对于第3层,它将在请求生命周期范围内解析,因此它将像Per Request
一样工作。在Layer1中解析你的类型时你应该小心,你可以开始新的生命周期。
除了这个外,因为你正在使用Func<IRepository<Folder>>
,所以它不会坚持单身。
注意:
你可以让它readonly
以确保我们不会在运行时更改它。
private Func<IRepository<Folder>> _foldersRepoFactory;