在下面的简化示例中,我有一个 DataContext 和 Repository,我认为它们以相当合理的方式定义:

public interface IUnitOfWork
{
   int SaveChanges();
}

public class DataContext : DbContext, IUnitOfWork
{
    public DbSet<Car> Cars { get ; set; }
}

public interface ICarsRepository
{
    Car Find(int id);
    void Add(Car car);
}

public class SqlCarsRepository : ICarsRepository
{
    private DataContext  _context;
    public SqlCarsRepository(DataContext context)
    {
       _context = context;
    }

    public Car Find(int id)
    {
        return _context.Cars.Find(id);
    }

    //etc
}

我正在努力弄清楚如何使用 DI 和抽象工厂模式来实现我想要的。在 MVC 应用程序中,这很容易设置 - Controller 将需要在其构造函数中实现 IUnitOfWork 和 ICarsRepository 的实例。我可以将容器配置为使用不同的 Controller 工厂为每个 Http 请求提供相同的 DataContext 实例。不知何故,这里的一次性依赖似乎被正确处理。

但是我想在 Windows 服务中使用相同的存储库。这是多线程的,每个线程在启动时都需要访问自己的存储库,每个线程都应该有自己的 DataContext/UnitOfWork。但我不知道如何做到这一点:
  • 应用程序的复合根是服务启动时,因此无法为每个线程解析依赖关系(线程按需启动)。
  • 我不确定如何使用抽象工厂模式。该线程需要 IUnitOfWork 和 ICarsRepository 的实例,但共享相同的 DataContext。我可以创建一个抽象工厂来在一次调用中创建它们,并将其传递到线程中,但是我不知道如何处理 DataContext。我不希望线程必须关心它对 ICarsRepository 实现的依赖是一次性的。我绝对不希望线程知道 ICarsRepository 依赖于 DataContext,因为这样似乎没有接口(interface) - 线程可以只依赖于 SqlCarsRespository。
  • 我不想让 SqlCarsRepository 一次性并让它处理 DataContext,因为可能有其他人使用 DataContext,并且它没有首先创建它。
  • 我以为我可以创建一个隐藏 IUnitOfWork 和 ICarsRepository 的 CarsService(并使用抽象工厂获取它的实例),但我仍然不知道如何处理 DataContext 依赖项

  • 做我正在尝试的最佳方法是什么?

    最佳答案



    他们可以,事实上,他们应该。您应该在每个线程的开头解析一个新的对象图。不这样做,意味着您只能使用线程安全的依赖项,而您的情况并非如此。



    我认为首先,尝试将您的 DataContext 定义为 MVC 应用程序中的 Per Web Request,以及 Windows 服务中的 Per Lifetime Scope(或您使用的容器中可用的任何内容)。在您的 Windows 服务中,每个线程都将获得自己的生命周期范围。定义范围通常允许您在范围结束时处理实例。



    您的线程应该关心这一点,但您的业务逻辑不应该关心。启动新线程时,您将必须拥有一些基础结构代码,以允许启动和结束范围,以及解析和使用图的根类型。这段代码应该是你的组合根的一部分,所以应用程序的其余部分应该忽略这一点。如果您使用 Per Lifetime Scope(或其他一些显式生命周期)注册了某些类型,您的容器将知道何时处置这些实例。基础设施代码只需要告诉容器范围已经结束。


    SqlCarsRepository 应该依赖于一个没有实现 IDisposable 的接口(interface),在这种情况下没有什么可以处理的。它应该是负责处理 DataContext 的容器,并且通过适当的注册您可以做到这一点。



    你的设计听起来很合理,但这里有一些其他的 SO 问题,它们可能会给你更多的工作:

  • One DbContext per web request…why?
  • Dependency injection in thread that create objects
  • Working with DI in multi-threaded applications.
  • 关于c# - 使用 DI/抽象工厂模式时的依赖处理,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11242166/

    10-12 01:21
    查看更多