views:

1772

answers:

4

Using ASP.NET MVC, I've implemented an autocomplete textbox using the approach very similar to the implementation by Ben Scheirman as shown here: http://flux88.com/blog/jquery-auto-complete-text-box-with-asp-net-mvc/

What I haven't been able to figure out is if it's a good idea to cache the data for the autocomplete textbox, so there won't be a roundtrip to the database on every keystroke?

If caching is prefered, can you guide me in the direction to how to implement caching for this purpose?

+2  A: 

You have a couple things to ask yourself:

  1. Is the data I'm pulling back dynamic?
  2. If not, how often do I expect this call to occur?

If the answers are, 1- not really and 2 - call to happen frequently, you should cache it.

I don't know how your data access is setup, but I simply throw my data into cache objects like so:

public IQueryable<Category> FindAllCategories()
{
    if (HttpContext.Current.Cache["AllCategories"] != null)
        return (IQueryable<Category>)HttpContext.Current.Cache["AllCategories"];
    else
    {
        IQueryable<Category> allCats =  from c in db.Categories
                                          orderby c.Name
                                          select c;

        // set cache
        HttpContext.Current.Cache.Add("AllCategories", allCats, null, System.Web.Caching.Cache.NoAbsoluteExpiration, new TimeSpan(0, 0, 30, 0, 0), System.Web.Caching.CacheItemPriority.Default, null);
        return allCats;
    }
}

This is an example of one of my repository queries, based off of LINQ to SQL. It first checks the cache, if the entry exists in cache, it returns it. If not, it goes to the database, then caches it with a sliding expiration.

Chad
@Chad, I have a question. It seems like LINQ2SQL love to do lazy loading so in your answer, it might possibly cached the "query" instead of the result, that means even the cache is there, it might query the database everytime it is used. I am not quite sure if I am right or not, please check the profiler or log to confirm this.
xandy
@xandy, good call. Let me look. I've only verified that if the cache object is hit, it does not hit the DB code.
Chad
Update: I verified that the data is indeed in the cache object, not the query. However, I did find in a couple other places that the query was in the cache - not the data. I didn't cache the same was as I mentioned above, but it does bring up a good point - make sure you check that the content cached is indeed the correct content. Thanks xandy.
Chad
Seems like a solution. But wouldn't it also be a solution to cache it on the client? I'm searching for application names, an string array with ~1500 entries.
Tommy Jakobsen
@Chad, you mentioned "a couple other places that the query was in the cache", do you find in which context it cache query, which context it cache data?
xandy
@xandy - oh, I was just messing around with caching and hadn't made sure the queries were running before caching. It's still a valid point tho, to run through the debugger and verify that the data is cached instead of the query - thx.
Chad
@Tommy - Caching on the client would just be a matter of creating a javascript array of each record. It's up to you if you wanted to store ~1500 entries on the client - which could be rebuilt on every visit (unless you saved it into a cookie). Server side caching would remove the round trip to the database, you'd be hitting the memory on the web server - making it 1 round trip instead of 2.
Chad
+3  A: 

You sure can Cache your result, using the attribute like:

[OutputCache(Duration=60, VaryByParam="searchTerm")]

ASP.net will handle the rest.

xandy
I don't get this. Can you explin it or do you know of a good article?
Tommy Jakobsen
That's an attribute you put on top of a controller action. It did instruct the asp.net engine that it need to cache the result for the action (for a certain duration) and the result is cached depending on what particular parameter. Look at this one: http://www.asp.net/learn/mvc/tutorial-15-cs.aspx
xandy
A: 

I think caching in this case would require more work than simply storing every request. You'd want to focus more on the terms being searched than individual keys. You'd have to keep track of what terms are more popular and cache combinations of characters that make up those terms. I don't think simply caching every single request is going to get you any performance boost. You're just going to have stale data in your cache.

Sergey
A: 

Well, how will caching in asp.net prevent server round trips? You'll still have server round trips, at best you will not have to look up the database if you cache. If you want to prevent server roundtrips then you need to cache at the client side.

While it's quite easily possible with Javascript (You need to store your data in a variable and check that variable for relevant data before looking up the server again) I don't know of a ready-tool which does this for you.

I do recommend you consider caching to prevent round-trips. In fact I have half a mind to implement javascript caching in one of my own websites reading this.

Cyril Gupta
I think he's referring to database round trips (at least, that's what he said in his question). He's going to have web server round-trips, but he can reduce the DB round trips.
Chad
Hmm.. You're right. I guess i missed a couple words in the hurry to read it. But the idea about Javascript caching is pretty valid :)
Cyril Gupta
It is indeed - so long as it's not too much data... ;D
Chad
Thanks for your replies. When talking about a string array, how much is "not too much data"?
Tommy Jakobsen
Well if you ask me, I think you can stretch this not too much data theory quite a bit cause you're on the client side (most computers these have lots of memory). So you're not taxing YOUR server's memory. I think you should be safe with a couple hundred records. But remember you gotta retrieve those records from your website, so don't try to retrieve and store too much.
Cyril Gupta
It will be a string array with ~1500 entries. Do you think thats too much?
Tommy Jakobsen
That sounds okay to keep in memory, but not to transfer from the server in one go. Also don't try to show more than 30-40 at a time through DOM manipulation using Javascript.
Cyril Gupta
But I need to do this in one go from the server, no? How can I avoid this? I've made it work now, so when the user loads the page, it populates an javascript array with all 1500 names.
Tommy Jakobsen
@Tommy - I think if, on page load, you displayed a message saying something like "loading data, please wait..." while you downloaded the data into a javascript array, it would be alright. However, you should also store it in a cookie so the user doesn't have to download it again. This opens up all new headaches (cookies off, reading/writing cookie, etc). Ultimately, a combination of Cyril's answer and mine would be the best solution.
Chad
I don't think storing in a cookie will work they have a 4kb limit. 1500 records ought be worth more. How much time do they take to download?
Cyril Gupta
The page is displayed almost instantly so I do not think it's a problem.
Tommy Jakobsen
instantly with 1550 records loaded from the db? Are you sure that some things are not getting cached locally? Are you testing on your own PC or on the server?
Cyril Gupta