调查或比较 Azure 离线数据同步中推送和拉取的数据

investigate or compare the data being pushed and pulled in Azure Offline data Sync

我有以下 Azure 移动客户端

public AzureCloudService()
{
    Client = new MobileServiceClient(AzureUrl, new CustomAzureClientMessageHandler());

}

并且我将以下消息处理程序附加到该客户端

   public class CustomAzureClientMessageHandler : DelegatingHandler
    {
        protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            // Do any pre-request requirements here
            request.Headers.Add("UserId", Settings.UserId);

            // Request happens here
            var response = base.SendAsync(request, cancellationToken);

            // Do any post-request requirements here
            return response;
        }
    }

我在以下行的帮助下将本地数据与服务器同步。

  // Push the Operations Queue to the mobile backed
            await Client.SyncContext.PushAsync();

 // Pull each sync table
            var table = await GetTableAsync<T>();
            await table.PullAsync();

问题是我需要investigate/compare同步推送和拉取的数据。

1) 有什么方法可以查看同步调用中推送和拉取的数据吗?可能正在使用我上面提到的消息处理程序?

2) 或者有什么方法可以在 Table Controller 而不是移动客户端上做同样的事情?

当同步出现问题时很难调试

https://blogs.msdn.microsoft.com/azuremobile/2014/04/07/deep-dive-on-the-offline-support-in-the-managed-client-sdk/

There are scenarios where you want to catch and deal with the synchronization conflicts in the client. You can control all the synchronization operations by implementing the IMobileServiceSyncHandler interface and passing it when initializing the context. For example, this is an implementation of a sync handler which traces all the operations which are happening.

classMySyncHandler : IMobileServiceSyncHandler
{
    MainPage page;

    public MySyncHandler(MainPage page)
    {
        this.page = page;
    }

    publicTask<JObject> ExecuteTableOperationAsync(IMobileServiceTableOperation operation)
    {
        page.AddToDebug("Executing operation '{0}' for table '{1}'", operation.Kind, operation.Table.Name);
        return operation.ExecuteAsync();
    }

    publicTask OnPushCompleteAsync(MobileServicePushCompletionResult result)
    {
        page.AddToDebug("Push result: {0}", result.Status);
        foreach (var error in result.Errors)
        {
            page.AddToDebug("  Push error: {0}", error.Status);
        }

        returnTask.FromResult(0);
    }
}

And we can use this synchronization handler by passing it to the overload of InitializeAsync in the sync context, as shown below:

var store = newMobileServiceSQLiteStore(StoreFileName);
store.DefineTable<TodoItem>();
AddToDebug("Defined table in the store");

var syncHandler = newMySyncHandler(this);
await client.SyncContext.InitializeAsync(store, syncHandler);
AddToDebug("Initialized the sync context");

我找到了实现 this.I 的解决方案,是通过关注 sample.Thanks 作者

获得的

https://github.com/Azure-Samples/app-service-mobile-dotnet-todo-list-files/blob/master/src/client/MobileAppsFilesSample/Helpers/LoggingHandler.cs#L12

解决方案是

  1. 扩展 SQLLite 存储以启用日志记录
  2. 使用消息处理程序进行日志记录

代码

/// <summary>
/// Extended SQlite Store which can log operations happen in the SQLite database
/// </summary>
public class MobileServiceSQLiteStoreWithLogging : MobileServiceSQLiteStore
{
    private bool logResults;
    private bool logParameters;

    public MobileServiceSQLiteStoreWithLogging(string fileName, bool logResults = false, bool logParameters = false)
        : base(fileName)
    {
        this.logResults = logResults;
        this.logParameters = logParameters;
    }

    protected override IList<JObject> ExecuteQueryInternal(string tableName, string sql,
        IDictionary<string, object> parameters)
    {
        Debug.WriteLine(sql);

        if (logParameters)
            PrintDictionary(parameters);

        var result = base.ExecuteQueryInternal(tableName, sql, parameters);

        if (logResults && result != null)
        {
            foreach (var token in result)
                Debug.WriteLine(token);
        }

        return result;
    }


    protected override void ExecuteNonQueryInternal(string sql, IDictionary<string, object> parameters)
    {
        Debug.WriteLine(sql);

        if (logParameters)
            PrintDictionary(parameters);

        base.ExecuteNonQueryInternal(sql, parameters);
    }


    private void PrintDictionary(IDictionary<string, object> dictionary)
    {
        if (dictionary == null)
            return;

        foreach (var pair in dictionary)
            Debug.WriteLine("{0}:{1}", pair.Key, pair.Value);
    }
}

/// <summary>
/// Message Handler which enable to pass the customer headers as well as logging the Request, Response etc happen via the Azure Mobile client
/// </summary>
public class CustomAzureClientMessageHandler : DelegatingHandler
{
    private bool logRequestResponseBody;

    public CustomAzureClientMessageHandler(bool logRequestResponseBody = false)
    {
        this.logRequestResponseBody = logRequestResponseBody;
    }

    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request,
        CancellationToken cancellationToken)
    {
        Debug.WriteLine("Request is being sent: {0} {1}", request.Method, request.RequestUri.ToString());

        if (logRequestResponseBody && request.Content != null)
        {
            var requestContent = await request.Content.ReadAsStringAsync();
            Debug.WriteLine(requestContent);
        }


        Debug.WriteLine("HEADERS in the request");

        foreach (var header in request.Headers)
        {
            Debug.WriteLine(string.Format("{0}:{1}", header.Key, string.Join(",", header.Value)));
        }

        var response = await base.SendAsync(request, cancellationToken);

        Debug.WriteLine("Response from server: {0}", response.StatusCode);

        if (logRequestResponseBody)
        {
            var responseContent = await response.Content.ReadAsStringAsync();
            Debug.WriteLine(responseContent);
        }

        return response;
    }
}