Mobile First Cloud First

A blog by Geert van der Cruijsen on Software Development, Cloud, DevOps & Apps

Tag: Xamarin.iOS

Xamarin apps: Sqlite vs Realm. What’s the best mobile DB solution?

Last week Realm.io introduced Realm for Xamarin. Realm promises an easy object database with full query options and better performance than existing solutions (so also sqlite which is probably the most used database solution). Time to put both sqlite and Realm to the test. which is better?

SqlitevsRealm (2)

When comparing these solutions i wanted to test out the full relational options of the database because that is what Realm advertises with. if we are looking at just plain key value storing we could use something like akavache (based on sqlite back end) which is probably faster because of lots of optimisations in queries. I do recommend using akavache for caching scenarios or when you are just storing simple types of data that do not require complex querying.

To test sqlite and Realm i’ve created a simple datamodel with orders and order lines. each order has a list of order lines and i would like to be able to query orders and get the underlying orders back immediately. but also the other way around. i would like to query certain orders which have order lines that contain a certain product. those kind of queries happen often when you are working in a real world business app.

So now we have this datamodel + some queries we want to execute. lets define some criteria on how to score both solutions. I came up with the following critters: Ease of use, speed, & maintainability.

let’s talk about these criteria in a bit more depth. I’ve created a sample project on github that has the samples and source code for you to experiment.

You can download the source here: https://github.com/Geertvdc/Xamarin-RealmVsSqliteCompare

Ease of use

Sqlite and Realm are both pretty easy to set up. I’ve used Sqlite in the past before and had never used Realm so i had to do some reading up on Realm. I didn’t have to read that much though because the basic explanation of Xamarin.Realm on the Realm.io site explains the most used features and all the features i need for this first test.

Realm is actually really simple to set up. Where Sqlite does require some plumbing (getting a location for a file to store your DB in and creating a SqlAsyncConnection) this is not needed for Realm. In Realm you can just call the GetInstance(); method and you are ready to go. For both we need to install nuget packages of course which can be though for sqlite as well since there are so many different packages it’s sometimes hard to know which ones to use.

Sqlite needs 3 nuget packages for the basic functionality:  SQLite.Net-PCL, SQLite.Net.Core-PCL and SQLite.Net.Async-PCL. next to that i use 2 extra packages to give me some extra extension methods: SQLiteNetExtensions & SQLiteNetExtensions.Async.

For Realm we just need to add Realm nuget package to all our projects.

After we have an instance of both Sqlite and Realm we can start inserting some data into our database. Below is some sample code to insert 1000 orders which each have 5 order lines. I want to be able to insert all of them and make sure that there is a relation stored between the orders and the order lines so i can retrieve both in 1 query.

Looking at the code Realm just works a bit easier. we don’t have to think about doing sql transactions (if you forget/remove the transaction it is about 3x slower.) We just need to create the objects in a Realm.Write block and Realm will handle all the things for us. I do have to say i’m no fan of having my database objects have to inherit from RealmObject and that the constructor has to be Realm.CreateObject() but more on that in the Maintainability criteria. When looking at ease of use only i have to say Realm is easier because it does all the plumbing and yak shaving for you. Winner: Realm

Speed

Realm promised us a faster database than the competition so this was the reason i started this investigation. Sqlite can be slow some times but most often this is because of bad use. Paul Betts (creator of Akavache) did a great session at Xamarin Evolve this year on why sqlite is often slow and how to use it properly. To test the speed I’ve created a xamarin forms app and ran some tests on both Android and iOS. speeds do change a bit from platform to platform and also there is a some difference in using a device or emulator/simulator. Overall Realm seemed a bit faster in querying complex queries and it seems to use some caching looking at the query that took 0 ms on iOS. A note here is that Sqlite can probably be even a bit faster when you optimize the queries. What i used now for Sqlite is just a generic query to retrieves all objects with it’s children.

Screen Shot 2016-05-17 at 13.52.12 Screenshot_20160517-135540

After looking at the test data there are some differences and sometimes Sqlite is faster then Realm and the other way around. Sqlite can be fast if you know what you are doing and Realm seems to do the job quite well without any special thought on how to do things like transactions. scoring points for ease of use again.

Winner: No clear winner between Sqlite & Realm purely regarding speed

Maintainability

The last criteria on which i wanted to test these 3 solutions is maintainability. Sure the ease of use of Realm seems nice but how would this work in actual apps that need to be maintained and tested for long periods of time.

The first think i noticed when looking at Realm is that all your database object need to inherit from RealmObject. Because of this inheritance Realm knows how to do all it’s magic but i really don’t like this approach. creating objects cannot be done by using a simple constructor you always need to use Realm.CreateObject, creating a tight reference to Realm. Same goes for the lists of objects within a RealmObject which have to be of the type RealmList<T>. I like Sqlites approach much better where you just use simple POCOs (Plain Old CLR Objects) with some attributes attached so Sqlite knows how to store certain things.

In a proper testable software architecture you want to keep the dependency on either Realm or Sqlite to a minimum of places and preferably only in the classes that handle the database communication. for Sqlite this is possible however for Realm this will be quite hard since creating new objects can only be done by Realm.CreatObject. You could do a mapping from Realm to POCOs in your repository but that defeats the purpose of the ease of use of Realm which offers functionality for listeners on object changes to easily update your UI.

another thing that is really missing from Realm is support for Async. In my opinion every mobile library should have async features as default (or as only option). It is on the “missing features” list of Realm so they are aware that this is an important feature. But at it’s current state in the beta it’s not in.

The last thing i noticed was the Fody Weaver that is being used by Realm. At first it’s not that important for you as a developer because it just works. the weaver will do some changes to your IL to add stuff Realm needs. As long as everything works it’s no problem, however when you run into problems you might have issues finding the issue because the code that is being executed is actually a bit different from what you wrote.

Combining these things related to maintainability i think Sqlite is a clear winner here.

Winner: Sqlite

Conclusion

Looking at these 3 criteria i think Sqlite is still the best solution. Sure Realm is pretty fast and needs almost no plumbing i think the maintainability of Sqlite will win it in the end. I do see some use for Realm, especially for POC’s or small projects. (although for POCs i have to much experience of POCs running in production in the end or growing to larger apps, if that is the case i would pick Sqlite).

We have to take into account that Realm is still in beta and Sqlite has been there for ages but the things i don’t like about Realm are basically in it’s base so i don’t see them changing that quite soon. I’ll be watching Realm to see what they are up to in the future but for now i’ll keep using Sqlite.

Let me know your experiences with Realm in the comments below. i’m curious if people have different opinions than me after playing with it for a few days.

Happy Coding

Geert van der Cruijsen

Continuous deployment of Xamarin.iOS apps to Hockeyapp using VSTS

Last week I’ve created 2 posts on setting up VSTS and Hockeyapp in a continuous deployment scenario for both Xamarin.Android and Windows 10 UWP apps. Today we’ll discuss the 3rd platform: Apps built using Xamarin.iOS

The basics of all 3 platforms are the same but there are still quite some differences so lets look at the steps for Xamarin.iOS apps:

image

Context: the app we are going to deploy

We’re going to deploy the same app as yesterday in the Xamarin Android post. I’ve created a simple solution in Visual Studio containing an average Xamarin project. 1 PCL, 1 Android app, 1 iOS app and 1 Windows 10 UWP app.

image_thumb1_thumb

To make things easier during automated build I’ve also created a new solution that only contains the projects relevant for the iOS app.

image-1

This solution only contains the PCL project and the Xamarin.iOS app project.

Setting up the build in VSTS: Prerequisites

 

There are some difficulties comparing the build of iOS apps to Android or Windows apps. first difficulty is that you are going to need a Mac to do the actual build steps. to do this you have 2 options. The first is to just use a Mac within your network and use that as a build agent, the other option is to use a service called MacInCloud.com which has a special plan for VSTS build agents.

Mac Build agent

Mac in cloud has a special VSTS build agent plan which only costs 30$ a month. in my experience this works really well. If you have a spare Mac somewhere to use as build agent this would also work fine but most clients I come don’t have that Winking smile

Setting up a VSTS build agent on a mac isn’t that hard. There is a good guide on this on github here: https://github.com/Microsoft/vso-agent/blob/master/docs/vsts.md

make sure Xamarin Studio is installed on the mac because it’s needed for doing the actual builds. (not in the VSTS build agent guide)

App Certificates

To be able to build the iOS app and to do ad-hoc distribution we’re going to need to set up certificates from the apple developer portal on our mac build agent. Xamarin has a great guide on how to do this so I won’t copy all the steps in this blogpost: https://developer.xamarin.com/guides/ios/deployment,_testing,_and_metrics/app_distribution/ad-hoc-distribution/

After we’ve arranged a mac build agent and set up the app certificates we can actually start building our app.

Setting up the build in VSTS

in VSTS open your team project and go to the BUILD tab. in here we’re going to create a new build definition by clicking the green + sign.

image_thumb3_thumb

Choose the Xamarin.iOS build template to set up the build.

image

In the next step select the correct repository you want to use for your app and make sure you select the Mac build agent in the drop down box.

image
Click Create and now our build definition is created with 2 out of the box steps. The first step is doing the actual Xamarin.iOS build. select the iOS specific solution so only the iOS related projects are build.

We’ll be removing the Xamarin test cloud step for now. if you want to know more about this let me know in a comment so I can create a new blogpost about this if people would like that.

image

so we only have the Xamarion.iOS step left but this will only build our app. we’re also going to need 2 extra steps which are not part of the Xamarin.iOS step:

  • Nuget package restore
  • Copy and Publish Artifacts.

Nuget Package restore:

I’ve you’ve read my previous posts on Android and Windows UWP you would expect we’re going to use the out of the box “restore nuget package” build step. But that is not possible for iOS. Why not? these steps are implemented using Powershell which doesn’t run on your mac agent. so we’ll have to do it manually by executing a shell script. So we’re going to create a shell script task. First we need to create the actual script. The script is quite simple. download the nuget.exe file and execute the nuget restore command

 

 

Save the .sh file in your repository so we can add it to our build step. Click the green + and select “Shell Script”

image

Drag the .sh script to the top of the build so the nuget restore will be executed before the actual build step. Select your .sh file in the script path and as argumenets pass in the path to your iOS solution file so the script knows what packages to restore.

image

Copy and Publish Artifacts

So we’ve set up the nuget restore and the build. the last step of our build is to copy and publish the build artificats  so we can send these to Hockeyapp later.

Add a “Copy and Publish Build Artifacts” step to your build definition.

image

In the copy and publish step set the root to the correct folder and for contents we’re going to select the .ipa file. The Artifact name we’re naming “drop” of type server.

image

These 3 steps should together be able to do a successful build. Go to triggers to schedule your build nightly or set it to build every time someone checks in code.

Queue a build to see if everything works.

image

Setting up Hockeyapp

I assume you’ve already created an account at Hockeyapp otherwise just sign up at www.hockeyapp.net (It’s free for 2 apps or less) once you’ve logged in go and create your first app by pressing the New App Button

image_thumb38_thumb

Hockeyapp will ask you to upload a build. we’re not going to do that since we’re setting up automatic deployments. choose to add the app manually

image_thumb40_thumb

Choose  iOS as the platform and fill in your release type and title of the app.

image

Click Save and in the overview of the app copy and save the App ID

image_thumb-19

To be able to deploy from VSTS we need to set up an API token we can use in VSTS. If you already followed the Android or Windows UWP guide you might have already taken these steps so you can skip these steps and move to the chapter of deploying the app.

Click on your user icon in the top right and select API Tokens from the menu on the left.

Create a new API token and call it VSTS. Copy this API token. we’ll need it in VSTS

image_thumb46_thumb

Move back to VSTS and  open up the marketplace (top right next to your name) and click manage extensions. browse the marketplace and install the Hockeyapp extension

image_thumb49_thumb

After installing the extension go back to your VSTS team project and navigate to the settings window. in the settings menu go to Services and add a new service Endpoint of type “Hockeyapp”

Give the endpoint a proper name and copy in the API token you’ve generated earlier. now save the service endpoint.

image_thumb51_thumb

Now all the plumbing with Hockeyapp is done we can actually start deploying our app to hockeyapp

Deploying your automated build to Hockeyapp

Go back to your team project in VSTS and navigate to the Release tab

image_thumb53_thumb

Choose an Empty deployment template and press OK.

image_thumb56_thumb

First go to the Artifact tab and select the build we’ve created earlier as supplier of the artifacts we’re going to release to hockeyapp.

image

Go back to Environments, name your deployment template and add a new Task

image_thumb60

This list should now contain a Hockeyapp step since we installed that as our extension

image_thumb62

Configure the Hockeyapp step by selecting the Hockeyapp connection from the list. (the service connection you’ve created earlier should be listed here) Enter the APP ID you copied earlier and select the .ipa file that was generated by the build.

image

That’s all it takes to set up the release. for the final step we’re going to set the triggers in the “Triggers” tab of the release to be deployed continuously after each build.

image

Press the Green + To start a manual release towards Hockeyapp. Everything should work and the release should be created in Hockeyapp.

If you have any questions let me know via twitter @geertvdc or by commenting below.

Happy coding!

Geert van der  Cruijsen