{"id":2249,"date":"2014-08-04T20:27:12","date_gmt":"2014-08-04T20:27:12","guid":{"rendered":"http:\/\/putridparrot.com\/blog\/?p=2249"},"modified":"2014-08-08T15:54:51","modified_gmt":"2014-08-08T15:54:51","slug":"exploring-akavache","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/exploring-akavache\/","title":{"rendered":"Exploring Akavache"},"content":{"rendered":"<p><a href=\"https:\/\/github.com\/akavache\/Akavache\" title=\"Akavache\" target=\"_blank\">Akavache<\/a> is a key-value store\/cache. It&#8217;s compatible with flavours of Windows including the desktop, WinRT and Windows Phone 8 as well as iOS, Mac and Android via Xamarin. It supports async await as well as RX observable.<\/p>\n<p><strong>Let&#8217;s code<\/strong><\/p>\n<p>We interact with Akavache via the BlobCache static class but before we do anything with Akavache we need to setup the application name. So at the first opportunity, such as when your applications starts you should supply Akavache with your application name.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nBlobCache.ApplicationName = &quot;MyApplicationName&quot;;\r\n<\/pre>\n<p>There are several different caches that we can use on the <em>BlobCache<\/em> object. Each implements the IBlobCache interface.<\/p>\n<ul>\n<li>The <strong>InMemory<\/strong> property is used for caching anything which is to be stored (as the name suggests) in memory and thus lost when the application shuts down.<\/li>\n<li>The <strong>LocalMachine<\/strong> is used to store data that is not related to the user&#8217;s account.<\/li>\n<li>The <strong>Secure<\/strong> is encrypted and is used to anything you want to store in a more secure manner.<\/li>\n<li>Finally the <strong>UserAccount<\/strong> is used to store data on a per user basis and can be part of a roaming profile.<\/li>\n<\/ul>\n<p>As stated on the <a href=\"https:\/\/github.com\/akavache\/Akavache\" title=\"Akavache\" target=\"_blank\">Akavache<\/a> readme.md, &#8220;on the desktop, your application&#8217;s data will be stored in the %AppData%\\[ApplicationName] and %LocalAppData%\\[ApplicationName]&#8221;.<\/p>\n<p><strong>Inserting data into the cache<\/strong><\/p>\n<p>There are several insertion methods (instance and extension methods) and overloads for each. I&#8217;m not going to go through each method and their overloads, instead let&#8217;s look at the insertion method you&#8217;ll most likely start with &#8211; inserting a single object.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nBlobCache.UserAccount.InsertObject(&quot;someObject&quot;, new SomeObject());\r\n<\/pre>\n<p>We supply a key, in this case the string <em>someObject<\/em> followed by an object. We can optionally supply a <em>DateTimeOffset<\/em> or <em>TimeSpan<\/em> to use as an expiration time, i.e. when the data is ejected from the cache.<\/p>\n<p>Ofcourse, if we insert more than one item with the same key, we&#8217;re simply going to overwrite the existing item, therefore updating the cache with the last inserted value.<\/p>\n<p><strong>Getting data from the cache<\/strong><\/p>\n<p>Once we&#8217;ve inserted items in the cache we&#8217;ll need a way to retrieve them. As can be seen from the <em>InsertObject<\/em> method we supply a key for our cached item. So we obviously use the same key to get the value from the cache. Akavache uses an asynchronous model for getting items from a cache so uses either an IObservable (the RX way) or getting values using async await. Here&#8217;s an example using the RX method<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nSomeObject result = null;\r\nBlobCache.UserAccount.GetObject&lt;SomeObject&gt;(&quot;someObject&quot;)\r\n   .Subscribe(i =&gt; result = i);\r\n<\/pre>\n<p>and here&#8217;s the same thing using async await<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nSomeObject result = await BlobCache.UserAccount.GetObject&lt;SomeObject&gt;(&quot;someObject&quot;)\r\n<\/pre>\n<p><strong>Getting data which is currently not cached<\/strong><\/p>\n<p>Obviously we don&#8217;t always start an application with the items already in the cache. So a common requirement is to query the cache for a value, if it doesn&#8217;t exist then get it from somewhere and then place it in the cache. Akavache offers a <em>GetOrFetchObject<\/em> method which allows the developer to to do just this. First we try to get an item from the cache and if it does not exist in the cache we can supply a Func&lt;Task&lt;T&gt;&gt; or Func&lt;IObservable&lt;T&gt;&gt; to get the item from somewhere else and it&#8217;s then automatically added to the cache for us.<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nSomeObject result = null;\r\nBlobCache.UserAccount.GetOrFetchObject(\r\n   &quot;someObject&quot;, \r\n   () =&gt; Task.Factory.StartNew(() =&gt; new SomeObject()))\r\n   .Subscribe(o =&gt; result = o);\r\n\r\n\/\/ or using async await\r\n\r\nSomeObject result = await BlobCache.UserAccount\r\n   .GetOrFetchObject(&quot;someObject&quot;, \r\n   () =&gt; Task.Factory.StartNew(() =&gt; new SomeObject()));\r\n<\/pre>\n<p>We can also pass an expiration DateTimeOffset to the above method.<\/p>\n<p><em>Note: GetOrFetchObject and GetOrCreateObject appear to do the same thing, both calling GetOrFetchObject which takes a Func&lt;IObservable&gt;. The former simply converts a Task&lt;T&gt; to an and IObservable&lt;T&gt; and the latter converts a Func&lt;T&gt; to an IObservable&lt;T&gt; also.<\/em><\/p>\n<p>An interesting other &#8220;get&#8221; method to look at is <em>GetAndFetchLatest<\/em>. This will attempt to get a value from the cache and at the same time will use the supplied Func to get the value from some alternate place. So for example, let&#8217;s say you&#8217;re going to get a value from a webservice. This will return the current cached version (if one exists) and at the same time try to get the current value from the webservice. Hence two items may be returned.<\/p>\n<p>In use&#8230;<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nBlobCache.UserAccount.GetAndFetchLatest(\r\n   &quot;someObject&quot;, () =&gt; Task.Factory.StartNew(() =&gt; new SomeObject()))\r\n   .Subscribe(i =&gt; result = i);\r\n<\/pre>\n<p>In the above code the <em>result = i<\/em> will be called twice (assuming we&#8217;ve already inserted an object with the key &#8220;someObject&#8221; into the cache). As you&#8217;d expect from the previous description of this method, the first call would contain cached &#8220;someObject&#8221; value and the second would be the new object we&#8217;ve created in the task.<\/p>\n<p><strong>Removing items from the cache<\/strong><\/p>\n<p>Apart from setting an expiration for items as they&#8217;re added to the cache we can also use the method <em>Invalidate<\/em> to remove specific key values from the cache or <em>InvalidateAll<\/em> to remove\/clear all items from the cache.<\/p>\n<p>For example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nBlobCache.UserAccount.Invalidate(&quot;someObject&quot;);\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Akavache is a key-value store\/cache. It&#8217;s compatible with flavours of Windows including the desktop, WinRT and Windows Phone 8 as well as iOS, Mac and Android via Xamarin. It supports async await as well as RX observable. Let&#8217;s code We interact with Akavache via the BlobCache static class but before we do anything with Akavache [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[80,79],"tags":[],"class_list":["post-2249","post","type-post","status-publish","format-standard","hentry","category-akavache","category-caching"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2249","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=2249"}],"version-history":[{"count":27,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2249\/revisions"}],"predecessor-version":[{"id":2307,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/2249\/revisions\/2307"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=2249"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=2249"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=2249"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}