0

I recently discovered the hard way that EF does caching. I have a root viewmodel that creates the initial DbContext. With every other viewmodel that gets created, I pass that context over. That way, I only have one connection, and I have dependency injection.

I have a function in one of the viewmodels that changes a state one of the entities. When I get attempt to get the entity back from the database, the status remains unchanged (I'm assuming this is due to caching).

All the other posts I've found (that's for EF 6), wants to create a NEW instance of the class, like this :

var context = new MyContext();

Which would work, but it would prevent me from having only one connection, and also eliminate my dependency injection.

Is there any other way of getting the true value of the entity?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
WynDiesel
  • 1,104
  • 7
  • 38
  • What is the lifetime of the context? Have a look: https://stackoverflow.com/questions/35696411/how-to-use-dependency-injection-with-entity-framework-dbcontext – M.Hassan Aug 26 '18 at 14:47
  • 1
    You should be creating a new instance of your context *per request*. – Justin Helgerson Aug 26 '18 at 14:49
  • 1
    This is a known issue with long lived contexts and entity tracking system. There are some ways to refresh the already tracked entity, but you'd better consider using no tracking queries. – Ivan Stoev Aug 26 '18 at 14:58
  • @IvanStoev, this is the answer that I'm looking for, thanks. Resolved my problem. If you add this as an answer, I'll accept. – WynDiesel Aug 26 '18 at 15:03
  • @M.Hassan the context is created per user login. It's a thick client, for a very small, 10 user intranet application. – WynDiesel Aug 26 '18 at 15:05
  • @JustinHelgerson, if this was a web-app, I would agree with you, or at least, a new context per web request. As mentioned in my above comment, the context is per user-login, for a thick client. – WynDiesel Aug 26 '18 at 15:06

1 Answers1

2

This is a known issue with long lived contexts and entity tracking system.

The DbEntityEntry class provides several methods to refresh the cached entity data - Reload, GetDatabaseValues, as well as detaching the entity from the change tracker (hence the cache) by setting the State to Detached. But they are applicable for single entity known in advance.

Also the old ObjectContext services provided a way to choose the query behavior via MergeOption enumeration - AppendOnly, OverwriteChanges, PreserveChanges and NoTracking. But all they are gone in DbContext services and the only remaining option is no tracking queries.

So anytime you want to be sure you'll get the actual database state, consider utilizing the no tracking queries by using .AsNoTracking() extension method. Just keep in mind that the returned entities are basically disconnected, so modifying them and applying the modifications back would be hard and can lead to exceptions like there is already entity tracked with the same key etc.

Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343