Siaqodb can be synchronized automatically with the SiaqodbCloud module to Azure Storage using the Open Source AzureTable.LiteClient.

Only Buckets from Siaqodb's DocumentStore can be synchronized with Azure Storage.

In order to synchronize clients with a master database, you will need three main components:

  • Siaqodb-powered client application (Clients)
  • Siaqodb-Cloud and AzureTable.LiteClient modules added to your client
  • Azure Storage account and table

Server Database Configuration

Azure Storage
First, add a reference to AzureTable.LiteClient to your client (the easiest way is to use Nuget). Use your Azure account information to access your Azure storage table.

AzureTableClient tableClient = new AzureTableClient("yourAccountName", "yourAccountKey");
AzureTable table = tableClient.GetTableReference("people");


SiaqodbCloud Client

Any Bucket from Siaqodb can be synchronized via SiaqodbCloud only if the bucket is marked as Sync-able. To mark it, you will have to call:

 Sqo.SiaqodbConfigurator.SetSyncableBucket("invoices", true);

To start sync-ing buckets, you will have to reference SiaqodbCloud.dll assembly which can be found inside the Siaqodb package. After you add the reference, create a SiaqodbSync instance by providing the AzureTable.LiteClient object to the SiaqodbSync object.

Example:

using SiaqodbCloud;
using Dotissi.AzureTable.LiteClient;
...
AzureTableClient tableClient = new AzureTableClient("yourAccountName", "yourAccountKey");
AzureTable table = tableClient.GetTableReference("people");
SiaqodbSync syncContext = new SiaqodbSync(table);

You can synchronize a Siaqodb local Bucket with an online Bucket by using Push/Upload and Pull/Download operations.

Upload all changes from an offline bucket to a cloud bucket:


IBucket bucket = siaqodb.Documents["invoices"];
syncContext.Push(bucket);//push local changes to server

Download all changes from the cloud bucket:

IBucket bucket = siaqodb.Documents["invoices"];
syncContext.Pull(bucket);//pull server changes to client db

Important note: every Pull() operation will call Push() first therefore Pull() will provide a complete Sync

Filtering

It does not always make sense to download all data from a cloud bucket to the local device. SiaqodbCloud allows you to filter and download only changes of records by a certain criteria, example:

 IBucket bucket = siaqodb.Documents["invoices"];
Filter f = new Filter("year");
f.Value = 2016;
syncContext.Pull(bucket,f); // pull server changes to client but only for filtered records

Conflicts

When an app runs with poor connections, and many concurrent users may do modifications on data, or even the same user using different devices, clearly conflicts may appear. SiaqodbSync can handle those conflicts and let developer decide based on business criteria, how to merge or what record is the "winner" of a conflict.

Conflicts are detected based on Document.Version property. This property is updated by server only at every UPDATE/DELETE/INSERT operation. The client code should never update this property.

Following types of conflicts may appear:

Delete - Delete: a record is deleted locally by one user, but the same record is deleted online by another user. When the synchronization is made, at push, a conflict appears;

Delete - Update: a record is deleted locally by one user, but the same record is updated online by another user. When the synchronization is made, at push, a conflict appears;

Update - Delete: a record is locally updated by one user, but the same record has been deleted online by another user. When the synchronization is made, at push, a conflict appears;

Update - Update: a record is locally updated by one user, but the same record is updated online by another user. When the synchronization is made, at push, a conflict appears;

By default, the online record is the 'winner', so for example on an update-update conflict, after a Push() operation occurs, the local Document changes are rejected and the server version is downloaded and stored locally.

However this behavior may be overridden and you may merge both conflicted documents or choose as winner based on app business criteria. To override these rules, you have to pass an instance of a class that implements 'IConflictResolver' to the Push/Pull methods. Example:

 private class LocalResolver : IConflictResolver
{
    public Document Resolve(Document local, Document online)
    {
        return local;
    }
}

And now you can pass an instance of this class to Pull/Push methods:

syncContext.Pull(bucket, new LocalResolver());//also calls Push()