views:

319

answers:

10

Let's say I have a list of categories for navigation on a web app. Rather than selecting from the database for evey user, should I add a function call in the application_onStart of the global.asax to fetch that data into an array or collection that is re-used over and over. If my data does not change at all - (Edit - very often), would this be the best way?

A: 

I use a static collection as a private with a public static property that either loads or gets it from the database.

Additionally you can add a static datetime that gets set when it gets loaded and if you call for it, past a certain amount of time, clear the static collection and requery it.

DevelopingChris
+1  A: 

If it never changes, it probably doesn't need to be in the database.

If there isn't much data, you might put it in the web.config, or as en Enum in your code.

Dana
Good point. The data can change and I was not clear about that in the question, so I've updated it. Sorry.
Mike
+1  A: 

Fetching all may be expensive. Try lazy init, fetch only request data and then store it in the cache variable.

Vadmyst
A: 

You'll find some pointers if you search questions tagged cache, caching, and singleton

rohancragg
+1  A: 

Premature optimization is evil. That being a given, if you are having performance problems in your application and you have "static" information that you want to display to your users you can definitely load that data once into an array and store it in the Application Object. You want to be careful and balance memory usage with optimization.

The problem you run into then is changing the database stored info and not having it update the cached version. You would probably want to have some kind of last changed date in the database that you store in the state along with the cached data. That way you can query for the greatest changed time and compare it. If it's newer than your cached date then you dump it and reload.

Ryan Roper
Awesome point! At the present, there are no issues. I'm sniffing around looking for bottlenecks when sessions raise fast - aka the slashdot/digg/reddit effect. The reload issue could be another question in itself.
Mike
+1  A: 

In an application variable.

Remember that an application variable can contain an object in .Net, so you can instantiate the object in the global.asax and then use it directly in the code.

Since application variables are in-memory they are very quick (vs having to call a database)

For example:

// Create and load the profile object
x_siteprofile thisprofile = new x_siteprofile(Server.MapPath(String.Concat(config.Path, "templates/")));
Application.Add("SiteProfileX", thisprofile);
Al
A: 

You may also want to check Microsoft Velocity Project. It might be overkill though.

Greg
+2  A: 

You can store the list items in the Application object. You are right about the application_onStart(), simply call a method that will read your database and load the data to the Application object.

In Global.asax

public class Global : System.Web.HttpApplication
{
    // The key to use in the rest of the web site to retrieve the list
    public const string ListItemKey = "MyListItemKey";
    // a class to hold your actual values. This can be use with databinding
    public class NameValuePair
    { 
        public string Name{get;set;} 
        public string Value{get;set;}
        public NameValuePair(string Name, string Value)
        {
            this.Name = Name;
            this.Value = Value;
        }
    }

    protected void Application_Start(object sender, EventArgs e)
    {
        InitializeApplicationVariables();
    }


    protected void InitializeApplicationVariables()
    {
        List<NameValuePair> listItems = new List<NameValuePair>();
        // replace the following code with your data access code and fill in the collection
        listItems.Add( new NameValuePair("Item1", "1"));
        listItems.Add( new NameValuePair("Item2", "2"));
        listItems.Add( new NameValuePair("Item3", "3"));
        // load it in the application object
        Application[ListItemKey] = listItems;
    }
 }

Now you can access your list in the rest of the project. For example, in default.aspx to load the values in a DropDownList:

<asp:DropDownList runat="server" ID="ddList" DataTextField="Name" DataValueField="Value"></asp:DropDownList>

And in the code-behind file:

protected override void OnPreInit(EventArgs e)
{
    ddList.DataSource = Application[Global.ListItemKey];
    ddList.DataBind();
    base.OnPreInit(e);
}
ADB
Nice solution with code sample - Cheers. I'd say this is real close to what I'm looking for.
Mike
+1  A: 

I would store the data in the Application Cache (Cache object). And I wouldn't preload it, I would load it the first time it is requested. What is nice about the Cache is that ASP.NET will manage it including giving you options for expiring the cache entry after file changes, a time period, etc. And since the items are kept in memory, the objects don't get serialized/deserialized so usage is very fast.

Usage is straightforward. There are Get and Add methods on the Cache object to retrieve and add items to the cache respectively.

Jeff - Great suggestion. I've had some issues with web caching since everything else on the page is dynamic, even the header. I've stayed away from it since I want a fresh copy everytime, so I like the app route. Whichever one provides once-a-month-convenient-refreshability is best.
Mike
A: 

Caching is the way to go. And if your into design patterns, take a look at the singleton.

Overall however I'm not sure I'd be worried about it until you notice performance degradation.

Smallinov