{"id":61,"date":"2011-08-24T01:02:20","date_gmt":"2011-08-24T05:02:20","guid":{"rendered":"http:\/\/blogs.visigo.com\/chriscoulson\/?p=61"},"modified":"2011-08-24T01:03:49","modified_gmt":"2011-08-24T05:03:49","slug":"simplify-your-caching-by-using-a-generic-method","status":"publish","type":"post","link":"https:\/\/blogs.visigo.com\/chriscoulson\/simplify-your-caching-by-using-a-generic-method\/","title":{"rendered":"Simplify Your Caching By Using a Generic Method"},"content":{"rendered":"<p>I needed to add caching to my data access routines to improve the performance of commonly accessed data. \u00a0This is pretty straightforward:<\/p>\n<ul>\n<li>Check to see if the cache entry already exists<\/li>\n<li>If the cache entry does exist, return the cached value<\/li>\n<li>If the cached entry doesn&#8217;t exist, fetch the data and add it to the cache.<\/li>\n<\/ul>\n<p>The problem was, I had a lot of data access routines that I wanted to add caching to. \u00a0Adding the 4 or 5 lines of code needed to do this to each routine would be tedious, and all of the repetition would be messy. \u00a0I knew I had to centralize my caching functionality in one place. \u00a0Since my data access routines returned many different types, I decided to use a generic method to perform the caching. \u00a0Since the data validation routines essentially had to be wrapped by this function (so that it&#8217;s only run if the value doesn&#8217;t exist in the cache), I call it using a statement lambda.<\/p>\n<div>Here&#8217;s what I came up with:<\/div>\n<div>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\n\/\/I use ASP.Net's cache object.  I get a reference to it with System.Web.HttpRuntime.Cache\r\n\/\/as I won't always be using it in the context of ASP.Net\r\nprivate static System.Web.Caching.Cache DataCache = System.Web.HttpRuntime.Cache;\r\n\r\npublic static T CacheFetch&lt;T&gt;(string key, Func&lt;T&gt; fetcher) where T:class\r\n{\r\n\t\/\/Don't bother with the caching if the key is null or blank\r\n\tif ((key ?? &quot;&quot;).Length &lt;= 0)\r\n\t{\r\n\t\treturn fetcher();\r\n\t}\r\n\r\n\tT result = DataCache&#x5B;key] as T;\r\n\r\n\tif (result == null)\r\n\t{\r\n\t\tresult = fetcher();\r\n\r\n\t\tif (result == null)\r\n\t\t{\r\n\t\t\tDataCache.Remove(key);\r\n\t\t}\r\n\t\telse\r\n\t\t{\r\n\t\t\tDataCache&#x5B;key] = result;\r\n\t\t}\r\n\t}\r\n\r\n\treturn result;\r\n}\r\n<\/pre>\n<p><span class=\"Apple-style-span\" style=\"font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px; white-space: normal;\">And here&#8217;s some examples of how I used it:<\/span><\/p>\n<\/div>\n<div><strong>Original data access routine:<\/strong><\/div>\n<div>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static IEnumerable&lt;Trustee&gt; GetTrustees(int infoReturnID)\r\n{\r\n\tInfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL));\r\n\r\n\tIEnumerable&lt;Trustee&gt; trustees = from trustee in context.Trustees\r\n\t\t\t\t\t\t\t\t\twhere trustee.InfoReturnID == infoReturnID\r\n\t\t\t\t\t\t\t\t\tselect trustee;\r\n\r\n\treturn trustees;\r\n}\r\n<\/pre>\n<\/div>\n<div><strong>Updated data access routine:<\/strong><\/div>\n<div>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static IEnumerable&lt;Trustee&gt; GetTrustees(int infoReturnID)\r\n{\r\n\treturn Common.CacheFetch&lt;IEnumerable&lt;Trustee&gt;&gt;(&quot;Trustees_&quot; + infoReturnID.ToString(), () =&gt;\r\n\t{\r\n\t\tInfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL));\r\n\r\n\t\tIEnumerable&lt;Trustee&gt; trustees = from trustee in context.Trustees\r\n\t\t\t\t\t\t\t\t\t\twhere trustee.InfoReturnID == infoReturnID\r\n\t\t\t\t\t\t\t\t\t\tselect trustee;\r\n\r\n\t\treturn trustees;\r\n\t});\r\n}\r\n<\/pre>\n<\/div>\n<div><strong>And another example:<\/strong><\/div>\n<div>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic static IEnumerable&lt;RevenueRange&gt; GetRevenueRanges()\r\n{\r\n\treturn Common.CacheFetch&lt;IEnumerable&lt;RevenueRange&gt;&gt;(&quot;RevenueRanges&quot;, () =&gt; {\r\n\t\tInfoReturnEntities context = new InfoReturnEntities(new Uri(Common.InfoReturnDataServiceURL));\r\n\r\n\t\tIEnumerable&lt;RevenueRange&gt; revenueRanges = from e in context.RevenueRanges\r\n\t\t\t\t\t\t\t\t\t\t\t\t  where e.RevenueRangeCD != &quot;?&quot;\r\n\t\t\t\t\t\t\t\t\t\t\t\t  orderby e.LowerLimit\r\n\t\t\t\t\t\t\t\t\t\t\t\t  select e;\r\n\r\n\t\treturn revenueRanges;\r\n\t});\r\n}\r\n<\/pre>\n<\/div>\n<p>My method was inspired by <a title=\"Generic cache method\" href=\"http:\/\/andreascode.blogspot.com\/2008\/05\/generic-cache-method.html\">this<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I needed to add caching to my data access routines to improve the performance of commonly accessed data. \u00a0This is pretty straightforward: Check to see if the cache entry already exists If the cache entry does exist, return the cached value If the cached entry doesn&#8217;t exist, fetch the data and add it to the [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[96,109],"tags":[321,94,106,95,105,108,103,100,98,104,102,101,320,97,69,99],"class_list":["post-61","post","type-post","status-publish","format-standard","hentry","category-net","category-performance-net","tag-net","tag-asp-net","tag-asp-net-cache","tag-c","tag-cache","tag-caching-2","tag-csharp","tag-data-access","tag-data-validation","tag-generic","tag-generic-method","tag-lambda","tag-performance","tag-validation-routines","tag-visual-studio","tag-web-caching"],"_links":{"self":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts\/61","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/comments?post=61"}],"version-history":[{"count":0,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/posts\/61\/revisions"}],"wp:attachment":[{"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/media?parent=61"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/categories?post=61"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.visigo.com\/chriscoulson\/wp-json\/wp\/v2\/tags?post=61"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}