title: Doing locking in ASP.NET correctly
body: <p>I have an ASP.NET site with a fairly slow search function, and I want to improve performance by adding the results to the cache for one hour using the query as the cache-key:</p>
  
  <pre><code>using System;
  using System.Web;
  using System.Web.Caching;
  
  public class Search
  {
      private static object _cacheLock = new object();
  
      public static string DoSearch(string query)
      {
          string results = "";
  
          if (HttpContext.Current.Cache[query] == null)
          {
              lock (_cacheLock)
              {
                  if (HttpContext.Current.Cache[query] == null)
                  {
                      results = GetResultsFromSlowDb(query);
  
                      HttpContext.Current.Cache.Add(query, results, null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
                  }
                  else
                  {
                      results = HttpContext.Current.Cache[query].ToString();
                  }
              }
          }
          else
          {
              results = HttpContext.Current.Cache[query].ToString();
          }
  
          return results;
      }
  
      private static string GetResultsFromSlowDb(string query)
      {
          return "Hello World!";
      }
  }
  </code></pre>
  
  <p>Let’s say visitor A does a search. The cache is empty, the lock is set and the result is requested from the database. Now visitor B comes along with a different search: Won’t visitor B have to wait by the lock until visitor A’s search has completed? What I really wanted was for B to call the database immediately, because the results will be different and the database can handle multiple requests – I just don’t want to repeat expensive unnecessary queries.</p>
  
  <p>What would be the correct approach for this scenario?</p>