Garden management with Azure, Part 2
In the first part of the ‘Garden management’ application, we created the SQL database and the web service in Azure, using Microsoft’s Azure Mobile SDKs. The functionality consisted mainly in a http controller allowing CRUD operations on the gardens. And the database scheme management using Entity Framework. To ensure this works, we created Integration Tests for the EF migrations and for actual http calls to the different endpoints.
The whole solution is to be found on Github, like mentioned in the former post:
https://github.com/StefanRiedmann/CicloGardens
In this second part, I want to create two client implementations for the Azure service and storage, using the Azure Mobile Client package. One will implement direct access, and the other one will implement offline synchronisation for the database and files.
The first concept for the client part contained the usage of two prereleased nuget packages from Microsoft’s Azure team
- Microsoft.Azure.Mobile.Client.Files (deprecated)
- Microsoft.Azure.Mobile.Server.Files (deprecated)
These packages provided logic and functionality to handle files, related to entries in a database table, and offline synchronisation.
When I was halfway through with the implementation, the dev team took it out of Github, so I suppose they decided not to support it anymore (unfortunatly, I didn’t find any explanations for this this decision). So I decided to step back from using this package. I’ll work on an own solution for this issue, and focus on the database access and synchronisation for this client.
I’ll implement this in a portable class library called ‘CicloGardensClient’ for Xamarin. This allows me to reuse it in different platform applications. For now, I won’t create a real user interface, but create the client implementation in a test-driven way, like I described in my post Developing in small circles. For this, there will also be a project called CicloGardensClient.IntegrationTest.
So let’s get started…
Add new project ‘Class Library’ for Xamarin.Forms (CicloGardensClient)
- Create the classes GardenOfflineClient.cs andGardenOnlineClient.cs which will implement two different ways to access the backend. With and without offline synchronisation
Add new project ‘Unit Test Project’ (CicloGardensClient.IntegrationTest)
- Add test classes GardenOnlineClientTest.cs and GardenOfflineClientTest.cs
- Add to each a test method ‘InstantiateGardenClient’ and create an instance of the client. You’ll see that you’ll need a project reference to the other project
Add nuget packages ‘Microsoft.Azure.Mobile.Client’ and ‘~.SQLiteStore’ to both projects.
Run the test, and the first setup is done.
First we need a ‘Garden’ class as representation of the stored data in the backend/SQL server. My first thought was to try to use the same class for them, so we could create a dll to be used in the server- and client-implementation. After a closer look, that’s not a good solution, as I will show. Alternatively we could create an interface IGarden, to make sure we implement the same properties and types on both sides. But to be honest, I even abandoned this idea, because of the following reasons:
- Even the interface can’t guarantee an harmonic implementation, because the server- and client-side could be published from different code versions
- When creating complex class structures, and using code-first-migrations from EntityFramework, interfaces can make this business kind of messy.
- The backend classes inherit from ‘EntityData’, which allows the version management and features some specialties of the azure backend sdk. We don’t want this dependency on the client side.
- The client side is frontend oriented, so we should focus that these classes are bindable.
- Real trustworthy compatibility between frontend- and backend-data can only be achieved with good and complete testing, and that’s what we’re going to do
Thinking of bindable frontend classes, brings me to the subject of Prism, which is one of my favorite frontend SDKs. I won’t go into details here, but I’ll use the baseclass ‘BindableBase’ for the class Garden.cs that we need here.
Now it’s time for the client implementations (GardenOnlineClient.cs and GardenOfflineClient.cs), which contains:
- Initialisation of the client and, for the offline version, the local sql database for offline synchronisation.
- Get/Set/Delete functions for gardens
The classes have a property
public Task<bool> Initializer
which can be used to ‘wait’ for the initialisation to finish (and to check the success). Mainly for tests, it’s quite handy.
Now let’s get back to the client classes. Well implement for each 3 functions, including the ‘Instantiate’ test:
- InstantiateGardenClient – let’s just wait for the Initialisation to finish, and make sure it does so with ‘true’ (=success)
- SetAndGetGarden – Save a garden, read it afterwards and make sure the object has been assigned an Id from the service
- DeleteGarden – Save a garden, check for success. Then delete it again and make sure it’s really gone
In the offline version, set/get/delete tests include Sync() calls, to sync the local database against the backend.
So now our application stack has 2 different client implementations.
- One with direct access to the backend. Here we have always need an internet connection and an available backend, but for many applications, this is sufficient, and it keeps the solution much less complex, because..
- the other implementation contains a local (client side) sql database, against which all CRUD operations of the app are running. This gives us much better performance, and the application can keep working even when internet connection or backend are not available. The disadvantage is that sync operations can take quite some times, and that concurrent operations on the same database entry lead to version conflicts, which have to be solved somehow. For many applications, you don’t want or need to go into that trouble
So, the next blog for this application will contain file access to Azure Storage.
So long…
HAPPY PLANTING