0

What is the best way to cache the following code. So the data is read once from database and served from cache every other time?

This will be accessed thousands of times in a day from multiple domains. I also want to be able to clear the cache when needed to refresh maybe the Pictures.

    // GETAll api/category
    [WebMethod(CacheDuration = 600)]
    public string GetAllCategories()
    {

        using (var db = new nopMass())
        {
            var cats = db.Categories
                        .Where(x => x.ParentCategoryId == 1
                                    && x.Deleted == false
                                    && x.Published == true)
                        .OrderBy(c => c.ParentCategoryId)
                        .ThenBy(c => c.DisplayOrder)
                        .AsEnumerable()
                        .Select(cat => new Category
                        {
                            Id = cat.Id,
                            Name = cat.Name,
                            Description = cat.Description,
                            MetaKeywords = cat.MetaKeywords,
                            MetaDescription = cat.MetaDescription,
                            MetaTitle = cat.MetaTitle,
                            PictureId = cat.PictureId,
                            DisplayOrder = cat.DisplayOrder,
                            CreatedOnUtc = cat.CreatedOnUtc,
                            Product_Category_Mapping = cat.Product_Category_Mapping,
                            ParentCategoryId = cat.ParentCategoryId,
                        })
                        .ToList();

            string XML = "";

            XML += "<Collection>";
            foreach (var item in cats)
            {
                XML += "<Category>";

                XML += "<Id>";
                XML += item.Id.ToString();
                XML += "</Id>";

                XML += "<Name>";
                XML += item.Name;
                XML += "</Name>";

                XML += "<Description>";
                XML += item.Description;
                XML += "</Description>";

                XML += "<MetaKeywords>";
                XML += item.MetaKeywords;
                XML += "</MetaKeywords>";

                XML += "<MetaDescription>";
                XML += item.MetaDescription;
                XML += "</MetaDescription>";

                XML += "<MetaTitle>";
                XML += item.MetaTitle;
                XML += "</MetaTitle>";

                XML += "<PictureUrl>";
                try
                {
                    XML += GetPictureUrl(item.PictureId);
                }
                catch { }
                XML += "</PictureUrl>";

                XML += "<DisplayOrder>";
                XML += item.DisplayOrder.ToString();
                XML += "</DisplayOrder>";

                XML += "<CreatedOnUtc>";
                XML += item.CreatedOnUtc.ToString();
                XML += "</CreatedOnUtc>";

                XML += "<ParentCategoryId>";
                XML += item.ParentCategoryId.ToString();
                XML += "</ParentCategoryId>";

                XML += "</Category>";
            }
            XML += "</Collection>";

            return XML;

        }
    }
Orion
  • 452
  • 6
  • 23
  • IMHO Use xmlseralization rather than hand-coded xml , see serialization http://stackoverflow.com/questions/4123590/serialize-an-object-to-xml – Eldho Feb 17 '17 at 08:50
  • When images are served using IIS it will be cached by default, if you change the url it will be new file hence it will be loaded. If you change the file with same name still it will be loaded to browser using the last modified property after that it will be cached. Also you can leverage browser local storage – Eldho Feb 17 '17 at 09:00
  • Is there a way to cache the Linq Query result, so I each request would not need to fetch the same results? – Orion Feb 19 '17 at 00:04
  • @Eldho I cannot use XMLSerialization as the Objects are generated by EntityFramework – Orion Feb 19 '17 at 00:05

1 Answers1

2

You should read about: HttpRunTime.Cache

First off you write to cache like this:

HttpRuntime.Cache.Insert(cacheKey, yourListOfObjects, null, DateTime.Now.AddMinutes(10), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);

This code holds your data for 10 minutes.

To read from the cache you can use this method:

public object ReadFromCache(string cacheKey)
    {

            if (HttpRuntime.Cache[cacheKey] != null)
            {
                var cache = HttpRuntime.Cache[cacheKey];

                if (cache != null)
                    return cache;
            }
            return null;

    }

Based on your code you can read from cache like this:

List<Categories> cats = (List<Categories>)ReadFromCache(cachekey);
if(cats == null)
{
   //your code to fetch
}

To clear the cache you can simply:

foreach (System.Collections.DictionaryEntry cacheItem in HttpRuntime.Cache)
                {
                    HttpRuntime.Cache.Remove(cacheItem.Key.ToString());
                }

Hope this helps.

NOTE: I havn't tested this but it should work

D. Dahlberg
  • 156
  • 1
  • 9