Don of the Day

Don of the Day


Adventures in software development with Xamarin and the Web

Software developer, building things with code in sunny Scottsdale, AZ.

Share


Twitter


Xamarin: Choosing a Data Store

Don FitzsimmonsDon Fitzsimmons

Data storage is going to be an early consideration for any app, and to complicate things, we're building a cross-platform app, which means our data store must work on all of the platforms we target. What's a data store that works on Android, iOS and Windows Mobile? You guessed it: SQLite. But, each of these platforms implements SQLite differently. Thankfully, we have options when storing data in our Xamarin app and SQLite isn't the only show in town.

In my experience there are three data storage libraries to consider for your Xamarin cross-platform app: 1) The SQLite.Net PCL by Frank Krueger which Xamarin docs outlines here. 2) Akavache, which is based on SQLite, but increases performance and ease of use among other things. 3) Realm, which is not based on SQLite, but is instead a data store created just for mobile apps. So, with these three options, which will I choose for my DownToZero app? Let's take a look at each one.

SQLite.Net PCL

My first attempt at creating a Xamarin cross-platform app quickly resulted in a Google search for how to use SQLite for data storage. I found this Xamarin document in the top five results, complete with an example that made use of the SQLite.Net PCL. Great! That is what I need. Upon trying to implement the example for my own app, I quickly found it to be cumbersome and it lacked many conveniences I was used to.

Now, this library was probably created early on when Xamarin was new and there was a need for some universal data storage library. Frank stepped up and created something that soon became the canonical data store for Xamarin. It's a great, well supported library and there's a ton of examples of how to use it out there. But it lacks certain conveniences that I wanted like ORM behavior and the ability to serialize certain data types.

Akavache

Aka-what? Yeah, funky name. This library was created originally by Paul Betts and he's gone to great lengths to make this data store very fast which he explains and demonstrates in this Xamarin Evolve '16 presentation. It's worth watching. Anyway, Akavache is capable of a lot more than just storing data, but my primary use of it so far is fairly simple. I can create an entity, using almost any types I want and Akavache stores it without issue. I like that.

Under the hood, Akavache is using SQLite3 to persist the data but there are all sorts of optimizations going on before the data gets there. I have been using it on a fairly large project and I haven't had any issues so far. It's been reliable and works on all of the major platforms.

Realm

This is the one data persistence library that's not based on SQLite. Realm is its own thing and designed specifically for mobile data storage. Only recently has Realm become available for Xamarin. Previously it was limited to iOS and Android and that's the case with their new Xamarin library currently. It doesn't work on Windows Mobile.

Realm is very fast and purpose-built, but there are some limitations. One limitation is that your POCO classes must inherit from RealmObject. That's not a big deal, but I'm not a fan of modifying POCO's to adhere to a data store's requirements.

Another problem I quickly found was that Realm objects must be read and written on the same thread. That effectively means you won't be using async await to write and read your data. I have read somewhere that Realm is so fast that the UI wouldn't be blocked during reads and writes, but I'm not sure about that.

There's also a lot of "magic" going on with the Xamarin/C# implementation of Realm when it comes to compile time. Under the hood, Realm is using Fody to modify your POCO's (presumably it's tweaking them at the IL level). This means you'll find some strange dependencies when you install the NuGet package.

What I'm Using

With these three choices and given my experience with each, I'm going to be using Akavache as my persistence store in the DownToZero app. I like that it's purpose-built for cross-platform apps, it's fast, it's reliable and it doesn't impose anything extraneous on my app.

Of course, I'll build my own data abstraction layer in such a way that it really won't matter which persistence library I choose now because I can swap it out for another later if my needs change. My typical data repository interface is quite simple and looks like this:

public interface IRepository
{
    Task SaveCountdownAsyc(Countdown countdown);
    Task<Countdown> GetCountdownAnsyc(string id);
    Task<IEnumerable<Countdown>> GetCountdownsAsync();
    Task DeleteCountdownAsync(string id);
}

With this simple interface I can create an implementation for the above data stores, with the exception of Realm, because none of my async methods would be useful since it's got that threading limitation.

The above interface will manage the storage of my very simple entity, which is just a POCO:

public class Countdown
{
    public string Id { get; set; }
    public string Name { get; set; }
    public DateTime EventDate { get; set; }
    public DateTime Created { get; set; }
    public string AccentColor { get; set; }
    public string BackgroundImageName { get; set; }
    public bool HasOneDayReminder { get; set; }
    public bool HasOneHourReminder { get; set; }
}

Next, I'll show what the implementation of this repository interface looks like. More to come...

Software developer, building things with code in sunny Scottsdale, AZ.

Comments