using System; using System.IO; using System.Collections.ObjectModel; using System.Diagnostics; using System.Threading.Tasks; using Microsoft.WindowsAzure.MobileServices; using Microsoft.WindowsAzure.MobileServices.SQLiteStore; using Microsoft.WindowsAzure.MobileServices.Sync; namespace DevDaysTasks { public partial class TodoItemManager { static TodoItemManager defaultInstance = new TodoItemManager(); MobileServiceClient client; IMobileServiceSyncTable todoTable; public async Task Initialize() { if (client?.SyncContext?.IsInitialized ?? false) return; client = new MobileServiceClient(Constants.ApplicationURL); var path = "syncstore.db"; path = Path.Combine(MobileServiceClient.DefaultDatabasePath, path); var store = new MobileServiceSQLiteStore(path); store.DefineTable(); //Initializes the SyncContext using the default IMobileServiceSyncHandler. await client.SyncContext.InitializeAsync(store); todoTable = client.GetSyncTable(); } public static TodoItemManager DefaultManager { get { return defaultInstance; } private set { defaultInstance = value; } } public MobileServiceClient CurrentClient { get { return client; } } public async Task> GetTodoItemsAsync(bool syncItems = false) { try { await Initialize(); if (syncItems) { await SyncAsync(); } var items = await todoTable .Where(todoItem => !todoItem.Done) .OrderBy(todoItem => todoItem.Name) .ToEnumerableAsync(); return new ObservableCollection(items); } catch (MobileServiceInvalidOperationException msioe) { Debug.WriteLine(@"Invalid sync operation: {0}", msioe.Message); throw; } catch (Exception e) { Debug.WriteLine(@"Sync error: {0}", e.Message); throw; } return null; } public async Task SaveTaskAsync(TodoItem item) { await Initialize(); if (item.Id == null) { await todoTable.InsertAsync(item); } else { await todoTable.UpdateAsync(item); } } public async Task SyncAsync() { await Initialize(); ReadOnlyCollection syncErrors = null; try { await client.SyncContext.PushAsync(); await todoTable.PullAsync( //The first parameter is a query name that is used internally by the client SDK to implement incremental sync. //Use a different query name for each unique query in your program "allTodoItems", todoTable.CreateQuery()); } catch (MobileServicePushFailedException exc) { if (exc.PushResult != null) { syncErrors = exc.PushResult.Errors; } } // Simple error/conflict handling. A real application would handle the various errors like network conditions, // server conflicts and others via the IMobileServiceSyncHandler. if (syncErrors != null) { foreach (var error in syncErrors) { if (error.OperationKind == MobileServiceTableOperationKind.Update && error.Result != null) { //Update failed, reverting to server's copy. await error.CancelAndUpdateItemAsync(error.Result); } else if(error.OperationKind != MobileServiceTableOperationKind.Update) { // Discard local change. await error.CancelAndDiscardItemAsync(); } Debug.WriteLine(@"Error executing sync operation. Item: {0} ({1}). Operation discarded.", error.TableName, error.Item["id"]); } } } } }