Reputation: 43
I am currently working on a .net MAUI app deployed to Android that features an offline sqlite datastore which is synced with an Azure Sql database. I have implemented this functionality with the Microsoft.Datasync.Client.SQLiteStore nuget package based on the tutorial (https://learn.microsoft.com/en-us/azure/developer/mobile-apps/azure-mobile-apps/quickstarts/maui/offline?pivots=vs2022-windows)
Working with the offline datastore works perfectly fine. I can add, delete and update elements. Also, upon trying to sync with the online azure sql datastore, adding and deleting elements works fine. However, updating for some reason keeps throwing a PushResult Error. I can't figure out from the error where exactly the problem lies, since adding and deleting works fine. Only updating elements causes the following error.
Microsoft.Datasync.Client.Offline.PushFailedException{Microsoft.Datasync.Client.Offline.Queue.TableOperationError}
public async Task SaveSurgeryAsync(SurgicalActivity item)
{
if (item == null)
{
throw new ArgumentException(nameof(item));
}
await InitializeAsync();
//await _table.PurgeItemsAsync("clinicalactivities", new PurgeOptions { DiscardPendingOperations = true });
ActivityServiceEventArgs<SurgicalActivity>.ListAction action = (item.Id == null) ? ActivityServiceEventArgs<SurgicalActivity>.ListAction.Add : ActivityServiceEventArgs<SurgicalActivity>.ListAction.Update;
if (item.Id == null)
{
await _surgeryTable.InsertItemAsync(item);
}
else
{
await _surgeryTable.ReplaceItemAsync(item);
}
SurgicalActivitiesUpdated?.Invoke(this, new ActivityServiceEventArgs<SurgicalActivity>(action, item));
}
this is my code for upserting the data from the local store to the azure sql datastore. I assume the base configuration is fine since adding and deleting works properly.
I'd appreciate any help. Also, I can more of my code if needed.
Upvotes: 1
Views: 556
Reputation: 313
@FabianK I did find where Adrian Hall posted a link to this article below, including the code snippet below, explaining how to better handle offline sync in a more real-world scenario. https://learn.microsoft.com/en-us/azure/developer/mobile-apps/azure-mobile-apps/howto/client/dotnet#synchronize-an-offline-table
public async Task SyncAsync()
{
ReadOnlyCollection<TableOperationError> syncErrors = null;
try
{
foreach (var offlineTable in offlineTables.Values)
{
await offlineTable.PushItemsAsync();
await offlineTable.PullItemsAsync("", options);
}
}
catch (PushFailedException exc)
{
if (exc.PushResult != null)
{
syncErrors = exc.PushResult.Errors;
}
}
// Simple error/conflict handling
if (syncErrors != null)
{
foreach (var error in syncErrors)
{
if (error.OperationKind == TableOperationKind.Update && error.Result != null)
{
//Update failed, reverting to server's copy.
await error.CancelAndUpdateItemAsync(error.Result);
}
else
{
// Discard local change.
await error.CancelAndDiscardItemAsync();
}
Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]);
}
}
}
This worked for me but I really don't understand why this is an acceptable solution. What seems to be happening is that my offline changes get pushed to the server, the server accepts and applies the changes and in the response back to my client I get the updated record, including an updated Version. It is when the client tries to update the offline table with the new Version that the error occurs. The solution seems to be to just assume that this scenario is what happened and force the offline database to take whatever value is returned from the server.
This could be me showing my ignorance from just beginning to understand this framework, but it seems not clean at all.
Upvotes: 0