【问题标题】:DbContext Lifetime with Depedency Injection依赖注入的 DbContext 生命周期
【发布时间】:2016-08-03 22:32:11
【问题描述】:

我对在我的 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.
   }
}

我遇到的问题是,这种模式导致我的所有存储库在我的程序启动时都被创建,因此MyContext 实例在整个程序中都存在。因此,当数据库在我的程序之外更新时,我的程序看不到新数据,因为 MyContext 正在使用对它已经加载的数据的引用。

如果这是一个 Web 应用程序,那么我会为每个请求创建新的依赖项,但由于这是 WinForms,我不明白如何在保持单个组合根且不通过 Unity 的情况下解决此问题我的程序周围的容器(或对其有静态引用),以便每个控制器都可以解决自己的每个实例依赖项。

这个问题的标准解决方案是什么,我在编写依赖项的方式/位置或使用 DbContext 时是否做错了什么?

我知道 MVC 更适用于 Web 应用程序,而 MVVM 或 MVP 之类的东西可能更适合非 Web 应用程序,但是它们都存在相同的问题,即单个组合根只被调用一次。

【问题讨论】:

  • 你解决了这个问题吗?
  • 我做了一个解决方案,但我不确定是否应该这样做。我创建了一个MyContextFactory,将其作为对所有存储库的依赖项注入(而不是注入MyContext),然后我使用该工厂在每个使用该上下文的方法中创建一个新的MyContext 对象。它有效,但我担心它可能不是推荐的处理方式。
  • 这个东西是 EntityFramework 上下文的麻烦。请参阅此博客条目,它很好地解释了这些问题并提供了解决方案mehdi.me/ambient-dbcontext-in-ef6

标签: c# entity-framework dependency-injection compositionroot


【解决方案1】:

这取决于您如何配置依赖注入,是单例还是每个范围一个实例。我知道在 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()

【讨论】:

  • 但是由于所有依赖项都在我的组合根目录中解析,然后我在MainController 中保留对这些依赖项的引用并将它们传递给程序,它们再也不会得到解析。我希望每个打开的新窗口都具有每个实例的生命周期的依赖项,但是我不知道如何在每次打开窗口时不再次解决我的依赖项的情况下实现这一点,我认为这是不好的做法。我的理解是组合根应该只被调用一次。
【解决方案2】:

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

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2018-06-19
  • 2021-02-07
  • 2017-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多