12

I have an ASP.NET MVC 3 app that is basically just a set of web services. These web services are exposed by a set of Controller actions. Each controller action queries my database. Because my data rarely changes, and, stale data is not a concern, I thought i would implement some cacheing to improve performance. My goals are:

  1. Never cache a response to a user.
  2. Cache the database records for up to 24 hours. If 24 hours has passed, hit the database again.

Does that make sense? I know how to prevent the response from caching. I just use the following:

HttpContext.Response.Cache.SetCacheability(cacheability)

However, I'm not sure how to cache my database records in memory for up to 24 hours. Does anyone have any suggestions on how to do this? I'm not even sure where to look.

Thank you

4
  • Do you simply want to cache the entire contents of a table into memory, or do you want to cache a portion using a LRU cache? Commented Jun 14, 2012 at 13:26
  • 1
    It doesn't sound like you're looking for a solution provided by the MVC framework. The MVC framework is designed to create responses for a user, and can cache those responses using the built-in OutputCache attribute. Since you don't want the responses cached, you might want to look for a more abstract method of caching query results that isn't tied to the MVC framework (memcached, etc.).
    – qxn
    Commented Jun 14, 2012 at 13:26
  • I want to cache the entire contents of a table into memory. Actually, in my instace, my table has already been converted to CLR objects. So, ideally, I would just like to cache the objects.
    – user70192
    Commented Jun 14, 2012 at 13:38
  • @user70192 -- Right. I don't think MVC is the right tool for that task. See my answer.
    – qxn
    Commented Jun 14, 2012 at 13:51

5 Answers 5

8

You can use the System.Runtime.Caching namespace (or the ASP.NET cache, but this is older and can only be used within web applications).

Here's a sample function which you can use to wrap around your current data retrieval mechanism. You can alter the parameters in MemoryCache.Add to control how much it's cached, but you requested 24h above.

using System.Runtime.Caching;    // At top of file

public IEnumerable<MyDataObject> GetData() 
{
    IEnumerable<MyDataObject> data = MemoryCache.Default.Get(MYCACHEKEY) as IEnumerable<MyDataObject>;
    if (data == null)
    {
        data = // actually get your data from the database here
        MemoryCache.Default.Add(MYCACHEKEY, data, DateTimeOffset.Now.AddHours(24));
    }
    return data;
}

As mentioned by @Bond, you may also wish to look at using an SQL Cache Dependency if the data you're caching is likely to change within the 24 hours. If it's pretty static though, this will do what you asked.

2
  • Being mostly stuck on .NET 3.5, I hadn't heard of this. It looks nice -- kind of like an out-of-the-box memcached. Is it distributable across multiple machines?
    – qxn
    Commented Jun 14, 2012 at 15:07
  • It's not across multiple machines, it's just an in-memory solution. It's exactly the same as the ASP.NET cache (System.Web.Caching) but available to non-ASP.NET applications as well.
    – Richard
    Commented Jun 14, 2012 at 15:11
2

The MVC framework is persistence-agnostic. There are no built-in means to store data, so there are no built-in means to cache stored data.

The OutputCache attribute can be used to cache a server response. But you explicitly stated that that's not something you want to do.

However, you may still be able to use the built-in OutputCache if you want to stay within the MVC framework. Consider exposing the data you want to cache as a JSON result

[OutputCache(Duration = 86400)]
public JsonResult GetMyData() {
    var results = QueryResults();
    return Json(results);
}

The JSON string at /ControllerName/GetMyData will be cached for 24 hours, so the actual query will only be ran once per day. That means you'd have to implement an AJAX call on your final page, or make another HTTP call from your server. Neither of those are ideal.

I would look for another solution to your problem outside of the MVC framework. Consider memcached, which was created for exactly this purpose.

2

What you are talking about is not exactly MVC responsibility. ASP.Net allow you to cahce only the things it produces (and this they are responces, obviosly).

If you want to cache data it can be better to cachet it the same place it was produced - somewhere in BL or Data Layer.

You can do something like that:

public class DataCacher
{
    private static String data;
    private static DateTime updateTime;

    private DataCacher() { }

    public static String Data
    {
        get
        {
            if (data == null || updateTime > DateTime.Now)
            {
                data = "Insert method that requests your data form DB here: GetData()";
                updateTime = DateTime.Now.AddDays(1);
            }
            return data;
        }
    }
}

String data presents your actual data here. After adding this class replace your GetData() methods with DataCacher.Data.

Hope it helps or at least leads you to some further thinking.

1

If you're using MSSQL you may want to look at SQL Cache Dependency.

I'm not sure if you can configure cache expiration to 24 hours but with the cache dependency you may not need to - it will invalidate the cache as soon as there is an update on the database(i.e. should be more efficient than the time expiration strategy).

0

Here is a good article which discusses several performance related practices for ASP.NET MVC 3 and caching is mentioned.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.