jahu
jahu

Reputation: 5657

Are there any risks in using static fields in an MVC application in the following scenario?

I have a validation annotations that detects swearwords. My swearwords are in database, but I want to keep them in memory to avoid unnecessary queries. I was thinking of adding a static list of swearwords (as plain old strings) to the validation annotation class and fill it up based on what I have in database when the validation is used for the first time during an application run. Are there any risks related to using such solution?

P.S. I don't really care if someone adds more words to the database during the run of the application. Having an incomplete list "till next restart" is good enough (the app is going to be restarted every day anyway).

Upvotes: 3

Views: 691

Answers (2)

Sergey Litvinov
Sergey Litvinov

Reputation: 7478

It would be better if you place it to HttpContext.Current.Cache with some expiration period. Then this data will be removed when it expires in cache, and then you can reload actual latest data. In that case actuality of the data will be better, than just static list.

You can write such code:

public static List<string> SwearWords
{
    get
    {
        List<string> items = HttpContext.Current.Cache["SwearWords"] as List<string>()
        if (items == null)
        {
            items = LoadThemFromDB();
            HttpContext.Current.Cache.Insert("SwearWords", 
                items, 
                null, 
                DateTime.Now.AddMinutes(10),
                Cache.NoSlidingExpiration);
        }
        return items;
    }
}

Then if you access this property first time - it will load them from DB and cache for 10 minutes. After ten minutes it will be removed from cache, and if it will be accessed again after it - it will load latest data and cache them again.

In case of static List you need to flush\update it manually in case if SwearWords in the DB updates.

You should also remember, then IIS stops application pool after 20 minutes of inactivity. So it will be automatically restarted if there aren't any users for 20 minutes. And this cache\static list will be also cleared within AppDomain

Followed by Markus comment - here is the same sample with double check that will avoid duplicate call of LoadThemFromDB in case if it will be called by more than one thread at the same time:

private static readonly object _swearWordsLockObj = new object();

public static List<string> SwearWords
{
    get
    {
        List<string> items = HttpContext.Current.Cache["SwearWords"] as List<string>()
        if (items == null)
        {
            lock(_swearWordsLockObj)
            {
                items = HttpContext.Current.Cache["SwearWords"] as List<string>()
                if (items == null)
                {
                    items = LoadThemFromDB();
                    HttpContext.Current.Cache.Insert("SwearWords", 
                        items, 
                        null, 
                        DateTime.Now.AddMinutes(10),
                        Cache.NoSlidingExpiration);
                }
            }
        }
        return items;
    }
}

This code named Double checked Locking - http://en.wikipedia.org/wiki/Double-checked_locking

Upvotes: 4

Eric Scherrer
Eric Scherrer

Reputation: 3388

As long as your list of swear words is thread safe for reading.

Consider using List<T> as is fine to read from multiple threads concurrently, so long as nothing's writing.

From the documentation:

A List<T> can support multiple readers concurrently, as long as the collection is not modified.

Upvotes: 1

Related Questions