3

I have a class running in a winforms app which uses EF Code First. The DbContext is created via DI through the class constructor. All works well.

The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.

I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?

Is there a true DI technique to achieve this? Or should I remove the context from the DI and use service location?

mattdwen
  • 5,288
  • 10
  • 47
  • 61

2 Answers2

0

Were you not happy with the answer to your other question (http://stackoverflow.com/questions/7657643/how-to-force-ef-code-first-to-query-the-database) which suggested using Detach, AsNoTracking or Overwrite Changes?

1) Maybe you could pass an interface that has the ability to create a DbContext, instead of the context itself.

using(var context = _contextFactory.Create()) {
  var entity = from table in  context.Blah...;
}

The Create method could either create the concrete class itself (defeating the DI pattern a bit), or use service location to have one created for it. Not that nice, but it's better than embedding service location calls everywhere and still means you're controlling the lifecycle yourself.

2) Change the WinForm to read from a webservice run by the website, effectively similar to disabling caching.

3) Deep in the heart of MVC (well not really that deep) it is referencing the DI container directly and using it as a service locator to pass as arguments for newly created objects. Technically you could do something similar in WinForms, but it would need you to split your application up into little chunks (controllers) that don't have a very long lifetime. Maybe it's worth looking at some MVC/MVP frameworks for WinForms, although I found myself cringing at most I saw after a quick google.

Betty
  • 9,109
  • 2
  • 34
  • 48
  • I thought I was having a separate problem, but I think I've just moved the problem deeper. I took the approach that @Betty has suggested in 1), though I'm going to have to be careful down the track when separate functions need to start referencing the context in regards to change tracking. – mattdwen Nov 21 '11 at 06:53
  • The factory suggested in 1) should be creating a new context everytime, not reusing it. – Betty Nov 21 '11 at 07:07
0

The problem is the data being referenced is also being modified via a web site, using the same DI pattern with EF Code First, and the data changes are not being reflected in the context instance in the winforms app.

This is a problem with your expectations.

If your web service and window forms app are in separate processes, they won't share in-memory data.

If you want to sync their in-memory data, simply re-query in one context after committing to the database in the other. This is the same as trying to share data between different SQL connections.

I can solve this by recreating the DbContext object in winforms every time I access it, but seems to be more of a service location pattern to me?

If you want to recreate the DbContext repeatedly, you could use an abstract factory to allow manual re-creation of the object, yet allow you to inject the specific implementation into the factory.

This is not (necessarily) the Service Locator pattern, and you would have to ensure that you manually dispose your DbContext instances. I'd give you some example code, but different DI containers have totally different ways of accomplishing a factory pattern.

Or you could simply make sure that you commit your data on the web service side, and re-query the data on the WinForms app side.

Merlyn Morgan-Graham
  • 58,163
  • 16
  • 128
  • 183