C# 依赖注入的DbContext生存期

C# 依赖注入的DbContext生存期,c#,entity-framework,dependency-injection,compositionroot,C#,Entity Framework,Dependency Injection,Compositionroot,我对在WinForms应用程序中使用依赖项注入来管理我的DbContext生命周期的正确方法感到困惑。现在,我有如下代码 static class Program { // This is the main window's controller, which stores all the // dependencies that are resolved in the composition root and handles // passing those depende

我对在WinForms应用程序中使用依赖项注入来管理我的
DbContext
生命周期的正确方法感到困惑。现在,我有如下代码

static class Program
{
   // This is the main window's controller, which stores all the
   // dependencies that are resolved in the composition root and handles 
   // passing those dependencies to other objects
   private static IMainController mainController;

   private static void ComposeDependencies
   {
      UnityContainer container = new UnityContainer();
      container.RegisterType<IMyContext, MyContext>();
      container.RegisterType<IOrderRepository, OrderRepository>();
      container.RegisterType<IOrderService, OrderService>();

      mainController = new MainController(
         container.Resolve<IOrderService>());
   }
}

public class OrderRepository : IOrderRepository
{
   private readonly IMyContext context;

   public OrderRepository(IMyContext context)
   {
      this.context = context;
   }
}

public class OrderService : IOrderService
{
   private readonly IOrderRepository repository;

   public OrderService(IOrderRepository repository)
   { 
      this.repository = repository;
   }
}

public class MainController
{
   private readonly IOrderService orderService;   

   public MainController(IOrderService orderService)
   {
      this.orderService = orderService;
   }

   public void DoSomethingWithAnOrder()
   {
      FirstTypeOfController controller = new FirstTypeOfController(this.orderService);

      // Show window, assign controller, etc.
   }

   public void DoSomethingElseWithAnOrder()
   {
      SecondTypeOfController controller = new SecondTypeOfController(this.orderService);

      // Show window, assign controller, etc.
   }
}
静态类程序
{
//这是主窗口的控制器,它存储所有
//在组合根和句柄中解析的依赖项
//将这些依赖项传递给其他对象
专用静态主控制器;
私有静态void复合依赖
{
UnityContainer容器=新的UnityContainer();
container.RegisterType();
container.RegisterType();
container.RegisterType();
mainController=新的mainController(
container.Resolve());
}
}
公共类OrderRepository:IOrderRepository
{
私有只读IMyContext上下文;
public OrderRepository(IMyContext上下文)
{
this.context=上下文;
}
}
公共类OrderService:IOrderService
{
专用只读IOrderRepository存储库;
public OrderService(IOrderRepository存储库)
{ 
this.repository=存储库;
}
}
公共类主控制器
{
专用只读IOrderService orderService;
公共主控制器(IOrderService orderService)
{
this.orderService=orderService;
}
公共无效DoSomethingWithAnOrder()
{
FirstTypeOfController=新的FirstTypeOfController(this.orderService);
//显示窗口、分配控制器等。
}
公共无效DoSomethingElseWithAnOrder()
{
SecondTypeOfController=新的SecondTypeOfController(this.orderService);
//显示窗口、分配控制器等。
}
}
我遇到的问题是,这种模式导致在我的程序启动时创建所有存储库,因此
MyContext
实例贯穿整个程序。因此,当数据库在我的程序之外更新时,我的程序看不到新数据,因为
MyContext
正在使用对它已经加载的数据的引用

如果这是一个web应用程序,那么每个请求都会有新的依赖项,但由于这是WinForms,我不知道如何在保持单个合成根的同时避免这个问题,而不在程序周围传递我的Unity容器(或静态引用它)因此,每个控制器都可以解决其自身的每个实例依赖关系

这个问题的标准解决方案是什么?在如何/在何处组合依赖项或使用我的
DbContext
时,是否存在一些错误


我知道MVC更适用于web应用程序,而类似MVVM或MVP的东西可能更适合于非web应用程序,但对于只调用一次的单个组合根来说,它们都会有同样的问题。

这取决于您如何配置依赖项注入,如果它是单实例还是每个作用域一个实例。我知道,在Ninject的DI框架上,您可以通过以下方式指定:

//Thread Scope (New instance on each injection)
kernel.Bind<IInterface>.To<ConcreteClass>().InThreadScope();


//Singleton Scope (One instance per application)
kernel.Bind<IInterface>.To<ConcreteClass>().InSingletonScope()
//线程作用域(每次注入时都有新实例)
kernel.Bind.To().InThreadScope();
//单例作用域(每个应用程序一个实例)
kernel.Bind.To()

这取决于您如何配置依赖项注入,如果它是单实例还是每个作用域一个实例。我知道,在Ninject的DI框架上,您可以通过以下方式指定:

//Thread Scope (New instance on each injection)
kernel.Bind<IInterface>.To<ConcreteClass>().InThreadScope();


//Singleton Scope (One instance per application)
kernel.Bind<IInterface>.To<ConcreteClass>().InSingletonScope()
//线程作用域(每次注入时都有新实例)
kernel.Bind.To().InThreadScope();
//单例作用域(每个应用程序一个实例)
kernel.Bind.To()

我看不出您的实现有任何问题,它看起来是正确的。没错,当程序启动时,您正在初始化存储库,这很好,并且在整个应用程序生命周期中保持上下文。对于存储库,您可以调用对数据库执行某些操作的方法;在获取数据的情况下,如果实现正确,无论发生什么情况,您都将获取最新的数据,除非您在应用程序加载时检索数据并将其存储在某个地方以备将来访问(例如全局变量、设置)。

我看不出您的实现有任何问题,它看起来是正确的。没错,当程序启动时,您正在初始化存储库,这很好,并且在整个应用程序生命周期中保持上下文。对于存储库,您可以调用对数据库执行某些操作的方法;在获取数据的情况下,如果实现正确,无论发生什么情况,您都将获取最新的数据,除非您在应用程序加载时检索数据并将其存储在某处以备将来访问(例如,全局变量、设置).

但由于所有依赖项都在我的合成根目录中解析,然后我在
MainController
中保留对这些依赖项的引用,并将它们传递给程序,因此它们再也无法解析。我希望在每个新窗口打开时,依赖项都具有每个实例的生命周期,但如果不在每次打开窗口时再次解析依赖项,我不知道如何实现这一点,我知道这是一种糟糕的做法。我的理解是,组合根只能被调用一次。但由于所有依赖项都在我的组合根中解析,然后我在
MainController
中保留对这些依赖项的引用,并在程序中传递它们,因此它们再也不会被解析。我希望在每个新窗口打开时,依赖项都具有每个实例的生命周期,但如果不在每次打开窗口时再次解析依赖项,我不知道如何实现这一点,我知道这是一种糟糕的做法。我的理解是,组合根应该只被调用一次。我也是这么想的,但是如果我通过实体框架获取一些数据,通过SQL更新数据,然后通过实体框架再次获取相同的数据,第二次通过EF获取数据时,我会