1
votes

I have a few repos/tables that get called alot returning thousands of rows in my website. I figured to help with the performance of the site, I should start caching the base data, then filter off of that for individual pages. Problem is, as soon as I implement the caching, my NHibernate session gets closed when that cache object is used/called.

I'm using MVC 4, Ninject, and the Repository Pattern.

I created a property on my page to handle accessing the cache object, just for a proof of concept. I'll refactor to it's own class later...

Anyway, here's the code:

private IQueryable<TournamentType> _tournamentTypes;
private IEnumerable<TournamentType> TournamentTypes
{
    get
    {
        _tournamentTypes = HttpRuntime.Cache.Get("TournamentTypes") as IQueryable<TournamentType>;

        if (_tournamentTypes == null)
        {
            //if (System.Web.HttpContext.Current.Application["TournamentTypes"] == null)
            //    System.Web.HttpContext.Current.Application["TournamentTypes"] = _tournamentTypeRepo.Query();

            //_tournamentTypes = System.Web.HttpContext.Current.Application["TournamentTypes"] as IQueryable<TournamentType>;

            _tournamentTypes = _tournamentTypeRepo.Query();
            HttpRuntime.Cache.Insert("TournamentTypes", _tournamentTypes);
        }

        return _tournamentTypes;
    }
}

Obviously the code that is running here was my last attempt. The commented-out code was the previous version that I tried. Neither work. As soon as I comment out all caching, and just call _tournamentTypeRepo.Query(), everything works fine.

Is there a different type of cache mechanism that I need to be using here?

Edit: I've got new information that may help here...

This is ONLY occurring when I'm running from localhost. As soon as the below code gets to my test environment (hosted on AppHarbor) it seems to work just fine (at least it's not throwing an exception saying the session is closed, or a nullreferenceexception).

Any other ideas as to why this wouldn't work only on localhost? I'd like to impelment this approach thoughout my application to speed it up, but if I'm not able to test this in my localhost environment, I'll be very gun-shy about doing anything.

1
"..Is there a different type of cache mechanism.." Have you checked NHibernate caching? query cache, object cache... How they are working? well they for sure do not cache the IQueryable... they cache the final SQL Select...Radim Köhler
[facepalm] no. Never even crossed my mind. I will definitely try that.ganders
Then your first steps should go here: nhibernate.info/doc/nh/en/index.html#performance-cache. Also, check this for more details: stackoverflow.com/a/26500666/1679310, it should provide all the details about how that worksRadim Köhler
I don't believe the above example will work for me since I'm not able to use SqlDependency. I'm still confused as to why the standard asp.net caching is affecting my NHibernate session. Should I be saving these values as a List() instead of the IQueryable?ganders
@RadimKöhler So I was doing some more searching on SO today and I spotted the MemoryCache feature that was implemented in .NET 4.0. It mentions that this is the new/suggested approach for caching. Is it a possibility the old style just doesn't work anymore [with NHibernate]? Here's a link to the implementation that I'm going to try: stackoverflow.com/questions/17653124/…ganders

1 Answers

1
votes

Finally got this figured out. Still not sure why it worked ok in non-localhost environments, but the issue was because I was returning an IQueryable object, and that needs to know of the context/session. As soon as I did a ToList() on the object, and cached the IEnumerable version, everything started working perfectly.

Beware, if someone follows this pattern, you will NOT be able to access nested objects from your cached version when lazy loading is turned on, since accessing those child objects would need to know of the context/session to "query" for that information.