1

Should I use akavache as a primary local database in my xamarin forms application or a cache database on top of another sqlite database? Because I cant find any example of how to update, insert, delete data in akavache object. For example,

   CacheItems= await BlobCache.LocalMachine.GetOrFetchObject<List<Item>>("CacheItems",
                  async () => await getdatafromAzure(recursive)); 

I am getting items from azure and store in local machine and these items are editable / deleteable or user can add a new item. How do I do it?

Emil
  • 6,411
  • 7
  • 62
  • 112
  • Did you test the other Get Insert and Delete methods? https://github.com/akavache/Akavache – Depechie Jan 30 '17 at 11:32
  • @Depechie maybe i didnt understand the purpose of insert but this creates total new object into akavache cache, not? await BlobCache.UserAccount.InsertObject("CacheItems", new item()); does this insert a new item insert into my CacheItems which has type as a list of items. – Emil Jan 30 '17 at 11:46
  • I thought the GetOr*** methods are just overloads that do the base calls for you. As long as you use the same cache key, I think you can get to all the items you need. – Depechie Jan 30 '17 at 11:47
  • Akavache is basically just a key/value store type DB so you can't really do partial updates to records stored in the DB like SQL Lite. It's two different storage concepts really. If you want to update just a field then you can just chain a get with an insert so Get the thing first then Update the field then Insert. In my application I'm just using Akavache for persistence so I always just have the models in memory and when i update them i push them to Akavache so if the app closes the object is still retained. What's your use case for using both? Seems excessive but maybe you have a good case – Shane Neuville Jan 30 '17 at 18:33
  • @ShaneNeuville that sounds exactly what I am looking for. I am still trying to understand akavache as I am newbie. how do you cache objects? using static object simply or can I use BlobCache.InMemory? Does BlobCache.InMemory same as BlobCache.LocalMachine but adds extra into memory or only in memory? – Emil Jan 30 '17 at 21:05

1 Answers1

5

Anything saved to LocalMachine gets persisted physically to the device. So on app or device restart it'll still be there (if the user hasn't removed the app or cleared the data that is)

As far as how to access/save there's lots of good samples here https://github.com/akavache/Akavache

Insert Object and Get Object are your basic access methods and then there's lots of extension methods like GetOrFetch, GetAndFetch, which are very useful

Here's a quick sample I haven't super tested to give one way to access stuff. It'd probably be better to use some of the extension methods but I figure an example like this is conceptually useful.

BlobCache.LocalMachine.GetObject<Tobject>(someKEy)
            .Catch((KeyNotFoundException ke) => Observable.Return<Tobject>(null))
            .SelectMany(result =>
            {
                //object doesn't exist in cache so create a new one
                if (result == null)
                    result = new Tobject();

                //apply whatever updates you are wanting to do
                //result.SomeField = "bob";

                //This will replace or insert data
                return BlobCache.LocalMachine.InsertObject(someKEy, result);

            })
            .Subscribe();

It's really all pretty boring stuff :-p Just get an object and store an object. Under the hood Akavache does a lot of really cool optimizations and synchronizations around that boring stuff though allowing it to be boring for the rest of us

In most of my cases when I start up a VM I retrieve the object from the cache and then just store it as some property on the VM or inside some service class. Then when any changes are made to the object I just insert it into the cache

BlobCache.LocalMachine.InsertObject(someKEy, result).Subscribe()

At that point I know now if the app closes down I'll have the latest version of that object right when user starts up app

The examples I gave are more the full Rx way of accessing... What you have in your original question works fine

        await BlobCache.LocalMachine.GetOrFetchObject<List<object>>("CacheItems",
              async () => await getdatafromAzure(recursive));

That will basically check the cache if it doesn't exist then it goes to Azure...

LocalMachine stores to physical device, InMemory just stores to some internal dictionary that goes away once the app is unloaded from memory, and UserAccount works with NT remoting accounts.

Shane Neuville
  • 2,127
  • 14
  • 19
  • Do you have to really check if it exist or when you do insert, it will already handle insert if not exist, update existing if it exist, or duplicates the value? btw, why do you add Subscribe suffix always? any good reason for that? – Emil Jan 31 '17 at 23:27
  • Basically I just implemented similar logic, I use a static list to hold in memory while app in use and everytime app is reinitialized i am filling it from akavache cache. thats why I was curious about InMemory option whether it already does this combination for me. So I dont need to use a static list. I couldnt find a detailed information about. – Emil Jan 31 '17 at 23:29
  • 2
    No you don't have to check. That was just me demonstrating getting and inserting. You could just insert before ever getting. But typically with a GET you'll still want to catch the KEyNotFoundException just in case. So if you're using TPL then you'd just try catch the get. If you're using GetOrFetchObject though then it just does all the magic for you. Just be aware that i'll always now exist in the cache and never fetch unless you set an expiration on it. – Shane Neuville Jan 31 '17 at 23:44
  • 1
    I haven't really used InMemory that much. It might give slightly better synchronization then your own list (which might not matter). InMemory (I'm pretty sure) it serializes and deserializes what you put in and take out so the object you put in is a different ref then what you retrieve. Whereas with a static list it's all the same ref. Which I only mention because that was relevant to me in an app I was doing :-) Also one might use it for a consistent data access patterns since they all implement the same interface. So you can swap them out in different scenarios. – Shane Neuville Jan 31 '17 at 23:50
  • One more note about inserting and getting. It's basically all the exact same pattern behind using a Dictionary<,> if you try to access a key in a Dictionary that doesn't exist you get an exception. But you don't have to check for the key whenever updating an associated value – Shane Neuville Jan 31 '17 at 23:59
  • lets say you are saving daily logs? are you saving as list object or insert each log with it is own key? What if when you want to fetch the latest log? this is very confusing with akavache – Emil Feb 20 '17 at 01:15
  • Well now you're starting to go beyond something that's specific to Akavache and is more about key value store NOSQL storage patterns. So it's hard to say what you should do. NOSQL has lots of repeated data for purposes of quick access so maybe for the latest log you store that into some key like "latestlog" or maybe like "Last10Days". Your best bet with that though is to look up some key value store patterns and see what type of structure works for you. – Shane Neuville Feb 20 '17 at 05:09
  • yea it seems like you are right. idea of akavache is really great and working really fast but such restrictions makes it not fully usable. I wish that they could extend something like AWS DynamoDB which allows 2nd hash key. – Emil Feb 20 '17 at 11:36