Autofac PerLifetimeScope与Web应用程序中的PerRequest

时间:2016-02-18 02:15:18

标签: asp.net-web-api dependency-injection autofac communication unit-of-work

使用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的行为。

enter image description here

希望我的问题很清楚。来自控制器(Http请求)的DbConext的行为是众所周知的。但是,当通过Tcp / Ip处理来自远程应用程序的请求时,DbContexts将如何表现?它会像每个事务的DbContext一样工作吗?

1 个答案:

答案 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会创建新的FoldersRepositoryDbContext个对象。

对于第二个_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;