1

I'm confused about the proper way to manage my DbContext lifetime using dependency injection in my WinForms application. Right now, I have code that looks like the following

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.
   }
}

The problem I'm having is that this pattern results in all of my repositories getting created when my program starts, so the MyContext instances stay around through the whole program. So when the database gets updated outside of my program, my program doesn't see the new data because MyContext is using references to the data that it already has loaded.

If this were a web application, then I'd have new dependencies made with every request, but since this is WinForms, I don't understand how to get around this problem while keeping a single composition root and without passing my Unity container all around my program (or having a static reference to it) so that each controller can resolve its own per instance dependencies.

What's the standard solution to this problem, and is there something that I'm doing incorrectly with how/where I'm composing my dependencies or using my DbContext?

I know that MVC is meant more for web applications and something like MVVM or MVP is perhaps more suited to non-web, but those would both have this same problem with a single composition root that only gets called once.

Ben Rubin
  • 5,557
  • 3
  • 24
  • 50
  • Did you manage to solve this problem? – Didzis Stivriņš Oct 03 '16 at 14:02
  • I made a solution, but I'm not sure whether it's how things should be done. I made a `MyContextFactory` that I inject as a dependency to all my repositories (instead of injecting `MyContext`), and then I use that factory to create a new `MyContext` object within each method that uses that context. It works, but I'm worried that it might not be a recommended way of handling this. – Ben Rubin Oct 04 '16 at 13:58
  • this stuff is a hassle with EntityFramework contexts. Please see this blog entry wich explains the problems very nicely and gives a solution https://mehdi.me/ambient-dbcontext-in-ef6/ – Tim van Peterson Aug 09 '18 at 12:10

2 Answers2

0

It depends on how you configured your dependency injection, if its Singleton or one instance per scope. I know that on Ninject's DI framework you can specify by using:

//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()
Rafael A. M. S.
  • 619
  • 1
  • 6
  • 26
  • But since all the dependencies are resolved in my composition root and then I keep references to those dependencies in `MainController` and pass them around the program, they never get resolved again. I want dependencies that have per-instance lifetimes with each new window that gets opened, but I don't know how to accomplish that without resolving my dependencies again each time a window is opened, which I understand to be bad practice. It's my understanding that the composition root should only get called once. – Ben Rubin Aug 03 '16 at 14:30
0

I dont see anything wrong with your implementation, it looks correct. That is right, you are initializing your repositories when your program starts, and that is good, and you keep your contexts for the entire application lifespan. With repositories, you call a method that performs some action against database; in case of fetching data, you always will get the latest data, no matter what, if implemented correctly, unless you would retrieve it on application load and store it somewhere for future access (like global variables, settings as an example).

lucas
  • 3,457
  • 6
  • 23
  • 42
  • 1
    That's what I thought too, but if I get some data through Entity Framework, update data through SQL, then get the same data again through Entity Framework, the second time I get data through EF, it still has the original value. I thought that I was doing something incorrectly, but I came across this second answer in this post which seems to confirm this behavior http://stackoverflow.com/questions/13138243/entity-framework-linq-query-finds-entries-by-original-data-but-returns-referenc – Ben Rubin Aug 03 '16 at 14:37
  • This post as well http://stackoverflow.com/questions/28042161/ef-returns-old-values – Ben Rubin Aug 03 '16 at 14:38