NHibernate caching issue - When to call Evict?
Asked Answered
L

1

7

I've run into an apparent caching issue where what's being returned by NHibernate is not matching up with what's in the DB.

I believe this is level2 cache data. It looks like I can use the Evict to do this, but when should the Evict method actually be called? For my particular application, the data is going to be unique to the user and chances are the data provided will only be used once*.

Can I disable Level2 caching for these sets of objects completely?

UPDATE 10/31

My scenario is this: I have a shopping cart where the customer is going to be adding and removing items. What I am doing is the following: before the updates to the cart are processed, I evict the Cart and CartProduct entities. Once this is done, I retrieve the list of CartProducts from the provider and return the view (this is happening in a .NET MVC Controller).

UPDATE 11/3

The shopping cart has since been finished, and I ran into an issue that appeared to be related to the same NHibernate issue, but in fact was an MVC issue. Deeper digging revealed that the HTML Helper extensions were overriding the value I supposed and replacing with what was in the Model state. So a double whammy on this one. Hope this helps someone.

Lout answered 30/10, 2012 at 0:57 Comment(0)
B
20

No, you cannot disable the cache for certain entities.

You do have several options:

  1. Use ISession.Clear() to clear all entities from NHibernate's cache.
  2. Use ISession.Evict( obj ) to clear a specific entity from the cache.
  3. Use ISessionFactory.Evict( typeof( obj ) ) to evict all entities/objects of a particular type from the cache. This would be the closest to what you are wanting in my opinion.
  4. Use the IStatelessSession to fetch the objects/entities from the database as this completely bypasses all caches.
Bontebok answered 30/10, 2012 at 3:20 Comment(3)
Randy, thanks for the links. Could you elaborate any more on the proper/intended usage of evit? I've made some notes above regarding my actual usage, but it seems to be a completely wrong way of doing it. It's ridiculous to me to have to call Evict before doing anything with the DB. Using MySQL FWIW.Lout
Evict() removes/disassociates an object from the NHibernate session. It's intended use is when you do not want an object persisted/saved back to the database. For example, you could load an existing shopping cart from the database, Evict() the shopping cart entities and persist the shopping cart entities in session. Then when the user gets to the end of the shopping cart, you could then save it back to the database. That example would allow your shopping cart to not have to be reloaded from the database with each page change. It's a bit of a contrived example but sounds reasonable.Bontebok
In regards to your second comment and the update to your question, yes, it does seem like something is not setup correctly as you shouldn't really be needing to Evict objects from the session for your use case. Unfortunately, I would need to know quite a bit about your application before we could narrow down the true problem. Some things to look into, ensure that you are not using the same entities as your view models, ensure you are using transactions, ensure you are properly committing your transactions before disposing over your NHibernate session.Bontebok

© 2022 - 2024 — McMap. All rights reserved.