Web 应用程序中的 Autofac PerLifetimeScope 与 PerRequest

Autofac PerLifetimeScope vs PerRequest in web applications

使用 Autofac DI 容器-

根据请求在我的 Web 应用程序中注册一个工作单元与将其注册为 PerLifetimeScope 有什么区别?

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 注册为单例,

FoldersRepository 注册为 PerDependency,

DbContext 注册为 PerRequest?适合我的情况吗?

编辑2:

我的应用程序结构是这样的:我的容器(LayersContainer 是单例并包含应用程序的所有层,因此层也是单例及其所有依赖项等等......当应用程序启动时我解析我的容器和所有组件也已解决。我的问题是,当我从第 1 层到达 SingletonDataService 时,我不知道 DbContexts 将如何表现。

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

PerLife Time Scope>Per Matching Lifetime Scope>Per Request这个命令从一般到具体。

Per Request 创建 'request' 标记 Per Matching Lifetime Scope 并为您管理生命周期。

Per Matching Lifetime Scope 创建标记 PerLifeTimeScope。如果您有嵌套的生命周期范围,这是合适的。 如果您使用此范围注册类型,则无法在另一个没有相同标签的生命周期范围内解析该类型(父生命周期范围也没有此标签)。因此它可以让您更好地控制 Per LifeTime Scope.

Per LifeTime Scope 创建一个对象,该对象由同一生命周期范围内的所有人共享。

Per Depency 每次解析时都会创建一个不同的对象。这不是共享的。

如果我们提出您的问题:

每次 _foldersRepoFactory() 被调用时都会在基础 class 构造函数中创建新的 FoldersRepository 对象和 DbContext 对象。但是 DbContext 对象只在一个请求中创建了 1 次并被所有其他人共享。

我在你的方法中多用了一个_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 容器创建新的 FoldersRepositoryDbContext 对象。

对于第二个 _foldersRepoFactory() 调用,Autofac Container 会创建新的 FoldersRepository 对象,但它使用之前的 DbContext 对象(不是创建新的 DbContext 对象),因为它们是在相同的请求生命周期范围内。

请求完成后,您的 mySingletonDataService 对象保留;您的 2 FoldersRepository 和 1 DbContext 对象已处理(假设 GC 收集)。

由于第 1 层,您不能使用 Per Request。您可以使用 Per Lifetime Scope。对于第 3 层,它将在请求生命周期范围内解析,因此它的行为类似于 Per Request。在 Layer1 中解析你的类型时你应该小心你应该开始新的 lifetimescope。

除此之外一切正常,因为您使用的是 Func<IRepository<Folder>>,所以它不会坚持单例。

注意: 你能做到 readonly 以确保我们不会在运行时更改它吗?

 private Func<IRepository<Folder>> _foldersRepoFactory;