1

Related question: How do I cache data that rarely changes?

I'm making an ASP.NET MVC4 application.

On every request the security details about the user will need to be checked with the area/controller/action that they are accessing to see if they are allowed to view it. The security information is stored in the database.

For example:

User
Permission
UserPermission
Action
ActionPermission

A "Permission" is a token that is applied to an MVC action to indicate that the token is required in order to access the action. Once a user is given the permission (via the UserPermission table) then they have the token and can therefore access the action.

I've been looking in to how to cache this data (since it rarely changes) so that I'm only querying in-memory data and not hitting a database (which is a considerable performance hit at the moment).

I've tried storing things in lists, using a caching provider but I either run in to problems or performance doesn't improve.

One problem that I constantly run in to is that I'm using lazy loading and dynamic proxies with EntityFramework. This means that even if I ToList() everything and store them somewhere static, the relationships are never populated. For example, User.Permissions is an ICollection but it's always null. I don't want to Include() everything because I'm trying to keep things simple and generic (and easy to modify).

One thing I know is that an EntityFramework DbContext is a unit of work that acts with 1st-level caching. That is, for the duration of the unit of work, everything that is accessed is cached in memory.

I want to create a read-only DbContext that will exist indefinitely and will only be used to read about permission data. Upon testing this it worked perfectly; my page load times went from 200ms+ to 20ms. I can easily force the data to refresh at certain intervals or simply leave it to refresh when the application pool is recycled. Basically it will behave like a cache.

Note that the rest of the application will interact with other contexts that exist per request as normal.

Is there any disadvantage to this approach? Could I be doing something different?

3

Yes, there are many problems with this approach.

First, The EF DBContext is not thread safe. If you make it static, then multiple users hitting this DbContext at the same time can cause data corruption, particularly if you're saving any items to the database. Even if it's read-only, you still have to deal with the fact that objects get inserted into the Local cache at runtime, and that's not thread-safe either.

Secondly, DbContexts are designed to be short-lived. There is no mechanism for cleanup. This means that if your app runs for months, it will contain this data for each user that has ever logged in, using more and more memory as it goes along until your worker process is restarted.

Third, You should really just cache your data you need in the Asp.NET Cache. This has mechanisms to expire data after a period of time, and is designed to deal with these situations.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.