Why can I only see my offline data in my Xamarin Forms app?

BoyoKendallBoyoKendall USMember ✭✭

I am having trouble or at least I think it's trouble with my Xamarin forms app, the concern is that I only seem to be returning offline data to my list even when I refresh it and I don't know why.

My app uses local storage in case the connection is lost and the user still needs to see data, it was my understanding that local storage will only be overwritten or updated when a PullAsync is used. Although I have defined this in my application it seems to still only return the stored data.

I checked the returned collection by setting a break point at Vessels.ReplaceRange(vessels); and I can see that the vessels collection is not the current data in my Azure database but the stored data that it collected the very first time the app was run.

No amount of refreshing or relaunching is helping. Do I need to set a purge on my local storage? or have I done something wrong within my code?

users.cs

using System;

namespace MyProject
{
    public class users
    {
        public string id { get; set; }
        public string name { get; set; }        
    }
}

AzureService.cs

[assembly: Dependency(typeof(AzureService))]
namespace MyProject
{
    public class AzureService
    {            
        public MobileServiceClient client { get; set; } = null;
        IMobileServiceSyncTable<users> vesselsTable;

        public async Task Initialize()
        {
            if (client?.SyncContext?.IsInitialized ?? false)
                return;

            var appUrl = "https://mysite.azurewebsites.net";

            client = new MobileServiceClient(appUrl);

            var path = "syncstore.db";
            path = Path.Combine(MobileServiceClient.DefaultDatabasePath, path);            
            var store = new MobileServiceSQLiteStore(path);

            store.DefineTable<users>();

            await client.SyncContext.InitializeAsync(store);

            vesselsTable = client.GetSyncTable<users>();
        }//initialize

        public async Task SyncVessels()
        {
            ReadOnlyCollection<MobileServiceTableOperationError> syncErrors = null;
            try
            {

                await client.SyncContext.PushAsync();                   
                await vesselsTable.PullAsync("allVessels", vesselsTable.CreateQuery());
            }
            catch (MobileServicePushFailedException exc)
            {
                if (exc.PushResult != null)
                {
                    syncErrors = exc.PushResult.Errors;
                }                
            }
        }//SyncVessels

        public async Task<IEnumerable<users>> GetVessels()
        {
            //Initialise & Sync
            await Initialize();
            await SyncVessels();
            return await vesselsTable.ToEnumerableAsync();
        }//GetVessels
    }//AzureService
}

VesselsPage.xaml.cs

 protected override async void OnAppearing()
        {
            base.OnAppearing();                

            CrossConnectivity.Current.ConnectivityChanged += ConnecitvityChanged;
            OfflineStack.IsVisible = !CrossConnectivity.Current.IsConnected;

            if (vm.Vessels.Count == 0)
                vm.LoadVesselsCommand.Execute(null);
            else
            {
                vm.LoadVesselsCommand.Execute(null);
            }//else
        }//OnAppearing

VesselsViewModel.cs

namespace MyProject
{

    public class VesselsViewModel : BaseViewModel
    {           
        AzureService azure;
        public VesselsViewModel()
        {
            azure = DependencyService.Get<AzureService>();
        }//VesselsViewModel

        // #Observable Collections
        public ObservableRangeCollection<users> Vessels { get; } = new ObservableRangeCollection<users>();

        //
        // #Loading Message
        string loading;
        public string Loading
        {
            get { return loading; }
            set { SetProperty(ref loading, value); }
        }//Loading

        //
        // #Load Vessels Command
        ICommand loadVesselsCommand;
        public ICommand LoadVesselsCommand => loadVesselsCommand ?? (loadVesselsCommand = new Command(async () => await ExecuteLoadVesselsCommandAsync()));

        //
        // #Load Vessels
        async Task ExecuteLoadVesselsCommandAsync()
        {
            if (IsBusy)
                return;
            try
            {
                loading = "Loading Vessels...";
                IsBusy = true;

                //This always seems to be stored data.
                var vessels = await azure.GetVessels();
                Vessels.ReplaceRange(vessels);
            }//try
            catch (Exception ex)
            {
                Debug.WriteLine("Failed to load vessels" + ex);
                await Application.Current.MainPage.DisplayAlert("Sync Error", "Unable to sync vessels, you may be offfline", "OK");
            }//catch
            finally
            {
                IsBusy = false;
            }//finally
        }//ExecuteLoadVesselsCommandAsync        
    }//BaseViewModel
}

As I said I thought the await vesselsTable.PullAsync("allVessels", vesselsTable.CreateQuery()); would be the point where the new dta was grabbed from the database and returned but it appears the stored data is taking priority or something else may be going on.

The documentation states

Pull is performed by the IMobileServiceSyncTable.PullAsync method on a
single table. The first parameter to the PullAsync method is a query
name that is used only on the mobile device. Providing a non-null
query name results in the Azure Mobile Client SDK performing an
incremental sync, where each time a pull operation returns results,
the latest updatedAt timestamp from the results is stored in the local
system tables. Subsequent pull operations then only retrieve records
after that timestamp. Alternatively, full sync can be achieved by
passing null as the query name, which results in all records being
retrieved on each pull operation. Following any sync operation,
received data is inserted into the local store.

Even passing null as the query name to remove the teimstamp difference has not helped, I still only see local data. The local data was collected yesterday and the new that is being ignored was entered today. So there is a time diffrenece there anyway.

Note

My app should only be reading data from the Azure database and updaing the list accordingly, it never has to write anything to the Azure database.

Any help is as ever, appreciated.

Answers

Sign In or Register to comment.